.386
.model flat,stdcall
option casemap:none
;****************************************************************************************
include c:\masm32\include\windows.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\gdi32.inc
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\gdi32.lib
;****************************************************************************************
RGB macro red,green,blue
xor eax,eax
mov ah,blue
shl eax,8
mov ah,green
mov al,red
endm
;****************************************************************************************
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
CloseBtnProc proto :DWORD,:DWORD,:DWORD,:DWORD
MinBtnProc proto :DWORD,:DWORD,:DWORD,:DWORD
;****************************************************************************************
.data
DlgName db "DLG_MAIN",0
szCaption db "仿制金山毒霸的标题栏",0
.data?
hInstance HINSTANCE ?
hBmp1 dd ?
hBmp2 dd ?
hBmp3 dd ?
hBmp4 dd ?
hBmp5 dd ?
hBmp6 dd ?
hBmp7 dd ?
hCaption dd ?
hClose dd ?
hMin dd ?
bMouseDown dd ?
.const
IDI_MAIN equ 900
IDB_BITMAP1 equ 901
IDB_BITMAP2 equ 902
IDB_BITMAP3 equ 903
IDB_BITMAP4 equ 904
IDB_BITMAP5 equ 905
IDB_BITMAP6 equ 906
IDB_BITMAP7 equ 907
IDC_STATIC_CAPTION equ 2001
IDC_STATIC_MIN equ 2002
IDC_STATIC_CLOSE equ 2003
;****************************************************************************************
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,addr DlgName,NULL,addr DlgProc,0
invoke ExitProcess,eax
;对话框窗口过程**************************************************************************
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
local pt:POINT
local rect:RECT
local hDC:HDC
.IF uMsg==WM_CLOSE
invoke EndDialog,hWnd,NULL
.ELSEIF uMsg==WM_INITDIALOG
invoke SendMessage, hWnd, WM_SETTEXT, 0, addr szCaption
;加载图像
invoke LoadBitmap, hInstance, IDB_BITMAP1
mov hBmp1, eax
invoke LoadBitmap, hInstance, IDB_BITMAP2
mov hBmp2, eax
invoke LoadBitmap, hInstance, IDB_BITMAP3
mov hBmp3, eax
invoke LoadBitmap, hInstance, IDB_BITMAP4
mov hBmp4, eax
invoke LoadBitmap, hInstance, IDB_BITMAP5
mov hBmp5, eax
invoke LoadBitmap, hInstance, IDB_BITMAP6
mov hBmp6, eax
invoke LoadBitmap, hInstance, IDB_BITMAP7
mov hBmp7, eax
;子类化“关闭”和“最小化”按钮
invoke GetDlgItem, hWnd, IDC_STATIC_CAPTION
mov hCaption, eax
invoke GetDlgItem, hWnd, IDC_STATIC_CLOSE
mov hClose, eax
invoke SetWindowLong, hClose, GWL_WNDPROC, addr CloseBtnProc
invoke SetWindowLong, hClose, GWL_USERDATA, eax
invoke GetDlgItem, hWnd, IDC_STATIC_MIN
mov hMin, eax
invoke SetWindowLong, hMin, GWL_WNDPROC, addr MinBtnProc
invoke SetWindowLong, hMin, GWL_USERDATA, eax
mov bMouseDown, FALSE
;重新设置窗口大小
invoke GetClientRect, hWnd, addr rect
sub rect.right, 2
invoke SetWindowPos, hWnd, 0, 0, 0, rect.right, rect.bottom, SWP_NOZORDER or SWP_NOMOVE
;画出窗口的边缘线
.ELSEIF uMsg==WM_PAINT
invoke GetDC, hWnd
mov hDC, eax
invoke GetClientRect, hWnd, addr rect
sub rect.right, 1
sub rect.bottom, 2
invoke MoveToEx, hDC, 0, 30, NULL
invoke LineTo, hDC, 0, rect.bottom
invoke MoveToEx, hDC, 0, rect.bottom, NULL
invoke LineTo, hDC, rect.right, rect.bottom
invoke MoveToEx, hDC, rect.right, rect.bottom, NULL
invoke LineTo, hDC, rect.right, 29
mov eax, FALSE
ret
;改变对话框的背景色,为了和标题栏协调起来
.ELSEIF uMsg==WM_CTLCOLORDLG
RGB 0F0h, 0F0h, 0F0h
invoke CreateSolidBrush, eax
ret
;拖动窗口
.ELSEIF uMsg==WM_LBUTTONDOWN
invoke GetCursorPos, addr pt
invoke ScreenToClient, hWnd, addr pt
.IF pt.y<30 && pt.x<420
invoke SendMessage, hWnd, WM_NCLBUTTONDOWN, 2, 0
.ENDIF
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc endp
;“关闭”按钮窗口过程********************************************************************
CloseBtnProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
local pt:POINT
.IF uMsg==WM_NCHITTEST
mov eax, TRUE
ret
.ELSEIF uMsg==WM_LBUTTONDOWN
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp4
mov bMouseDown, TRUE
.ELSEIF uMsg==WM_MOUSEMOVE
invoke GetCursorPos, addr pt
invoke WindowFromPoint, pt.x, pt.y
.IF eax==hWnd
invoke SetCapture, hWnd
.IF bMouseDown
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp4
.ELSE
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp3
.ENDIF
.ELSE
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp2
.IF !bMouseDown
invoke ReleaseCapture
.ENDIF
.ENDIF
.ELSEIF uMsg==WM_LBUTTONUP
invoke GetCursorPos, addr pt
invoke WindowFromPoint, pt.x, pt.y
.IF eax==hWnd
.IF bMouseDown
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp3
invoke GetParent, hWnd
invoke SendMessage, eax, WM_CLOSE, 0, 0
.ENDIF
.ENDIF
invoke ReleaseCapture
mov bMouseDown, FALSE
.ELSE
invoke GetWindowLong, hWnd, GWL_USERDATA
invoke CallWindowProc, eax, hWnd, uMsg, wParam, lParam
ret
.ENDIF
xor eax,eax
ret
CloseBtnProc endp
MinBtnProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
local pt:POINT
.IF uMsg==WM_NCHITTEST
mov eax, TRUE
ret
.ELSEIF uMsg==WM_LBUTTONDOWN
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp7
mov bMouseDown, TRUE
.ELSEIF uMsg==WM_MOUSEMOVE
invoke GetCursorPos, addr pt
invoke WindowFromPoint, pt.x, pt.y
.IF eax==hWnd
invoke SetCapture, hWnd
.IF bMouseDown
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp7
.ELSE
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp6
.ENDIF
.ELSE
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp5
.IF !bMouseDown
invoke ReleaseCapture
.ENDIF
.ENDIF
.ELSEIF uMsg==WM_LBUTTONUP
invoke GetCursorPos, addr pt
invoke WindowFromPoint, pt.x, pt.y
.IF eax==hWnd
.IF bMouseDown
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp6
invoke GetParent, hWnd
invoke ShowWindow, eax, SW_MINIMIZE
.ENDIF
.ENDIF
invoke ReleaseCapture
mov bMouseDown, FALSE
.ELSE
invoke GetWindowLong, hWnd, GWL_USERDATA
invoke CallWindowProc, eax, hWnd, uMsg, wParam, lParam
ret
.ENDIF
xor eax,eax
ret
MinBtnProc endp
end start分析
invoke GetDlgItem, hWnd, IDC_STATIC_CAPTION
mov hCaption, eax
invoke GetDlgItem, hWnd, IDC_STATIC_CLOSE
mov hClose, eax
invoke SetWindowLong, hClose, GWL_WNDPROC, addr CloseBtnProc
invoke SetWindowLong, hClose, GWL_USERDATA, eax
invoke GetDlgItem, hWnd, IDC_STATIC_MIN
mov hMin, eax
invoke SetWindowLong, hMin, GWL_WNDPROC, addr MinBtnProc
invoke SetWindowLong, hMin, GWL_USERDATA, eax
mov bMouseDown, FALSE
首先取得“关闭”按钮和“最小化”按钮的句柄,然后分别子类化以截获消息处理消息。
invoke GetClientRect, hWnd, addr rect
sub rect.right, 2
invoke SetWindowPos, hWnd, 0, 0, 0, rect.right, rect.bottom, SWP_NOZORDER or SWP_NOMOVE
改变窗口的大小,主要是为了匹配标题栏的宽度。
.ELSEIF uMsg==WM_PAINT
invoke GetDC, hWnd
mov hDC, eax
invoke GetClientRect, hWnd, addr rect
sub rect.right, 1
sub rect.bottom, 2
invoke MoveToEx, hDC, 0, 30, NULL
invoke LineTo, hDC, 0, rect.bottom
invoke MoveToEx, hDC, 0, rect.bottom, NULL
invoke LineTo, hDC, rect.right, rect.bottom
invoke MoveToEx, hDC, rect.right, rect.bottom, NULL
invoke LineTo, hDC, rect.right, 29
mov eax, FALSE
ret
处理 WM_PAINT 消息,分别在窗口的左边、下边和右边画上边界线,这样一来有一种平面效果正好匹配我们的标题栏。
.ELSEIF uMsg==WM_LBUTTONDOWN
invoke GetCursorPos, addr pt
invoke ScreenToClient, hWnd, addr pt
.IF pt.y<30 && pt.x<420
invoke SendMessage, hWnd, WM_NCLBUTTONDOWN, 2, 0
.ENDIF
在鼠标按下时判断是不是在我们绘制的标题栏范围内,在这除去了右边“关闭”按钮和“最小化”按钮占去的位置。
.IF uMsg==WM_NCHITTEST
mov eax, TRUE
ret
返回 TRUE 从而实现鼠标消息的截获。
.ELSEIF uMsg==WM_LBUTTONDOWN
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp4
mov bMouseDown, TRUE
.ELSEIF uMsg==WM_MOUSEMOVE
invoke GetCursorPos, addr pt
invoke WindowFromPoint, pt.x, pt.y
.IF eax==hWnd
invoke SetCapture, hWnd
.IF bMouseDown
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp4
.ELSE
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp3
.ENDIF
.ELSE
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp2
.IF !bMouseDown
invoke ReleaseCapture
.ENDIF
.ENDIF
.ELSEIF uMsg==WM_LBUTTONUP
invoke GetCursorPos, addr pt
invoke WindowFromPoint, pt.x, pt.y
.IF eax==hWnd
.IF bMouseDown
invoke SendMessage, hWnd, STM_SETIMAGE, IMAGE_BITMAP, hBmp3
invoke GetParent, hWnd
invoke SendMessage, eax, WM_CLOSE, 0, 0
.ENDIF
.ENDIF
invoke ReleaseCapture
mov bMouseDown, FALSE在鼠标按下时加载按下效果的位图,并设置标志位标志鼠标处在按下状态。在 WM_MOUSEMOVE 消息中先取得鼠标位置,判断是否在按钮上,如果在按钮上,则锁定鼠标消息,然后根据鼠标是否正按下来加载按钮按下的位图或按钮加亮的位图。如果不在按钮上,则加载正常的位图,然后判断鼠标是否正处在按下的状态,如果不是,则说明只是鼠标经过按钮上而已,可以释放鼠标;如果正处在按下状态,则不能释放鼠标,因为如果这时候释放鼠标,当鼠标移出按钮然后弹起时我们就接收不到消息,所以要留到 WM_LBUTTONUP 消息中释放鼠标。在 WM_LBUTTONUP 消息中也是先取得鼠标位置,判断是否在按钮上,如果在,再判断鼠标是否处在按下状态,接着就可以发送消息实现按钮的功能。最后释放鼠标,设置标志位标志鼠标已经弹起。
CopyRight (C) 2001-2002 一块三毛钱
本文地址:http://com.8s8s.com/it/it29546.htm