Jump to content
Tuts 4 You

Mouseover Buttons


Guest Tundra

Recommended Posts

How do you test if a mouse is hovering over a certain button?

Take a close look at the code in the MASM library for "bmpbutton"

usually at

C:\masm32\m32lib\bmpbutn.asm

The bmpbutton proc just handles up/down but is easily extended to handle mouseover as well.

Also there is a bitmap button code example in the MASM package itself.

Z

Link to comment
Guest Tundra

But how do I actually test where the mouse button is? For example, you compare uMsg with WM_LBUTTONDOWN and WM_LBUTTONUP to see if there was a mouse press, what do you do to find if the mouse is over a button?

Link to comment
i think you have to sublass the button and check for WM_MOUSEMOVE

Yes subclass the "button" window. Then the WM_MOUSEMOVE message returns X and Y coordinates of the mouse position and you can use GetClientRect to get the X1, Y1, X2, Y2 rectangular coordinates of the button "window". If the mouse X,Y is inside the button rectangle change the button bmp to the "mouseover" bmp or do wtf else you want.

There is also a TrackMouseEvent API which looks like it should be useful but I have not seen used effectively for mouseover effects. If you get this working please post your code snippet :)

Z

Link to comment
Guest Tundra

Ok, I got it working. Here's the procedure I wrote for displaying bitmap buttons with a pressed image and a mouseover image. It's an edited version of masm32's BmpButton procedure.

MyBmpButton proc hParent:DWORD,topX:DWORD,topY:DWORD,rnum1:DWORD,rnum2:DWORD,rnum3:DWORD,ID:DWORD ; parameters are,
; 1. Parent handle
; 2/3 top X & Y co-ordinates
; 4/5/6 resource ID numbers or identifiers for UP/DOWN/MOUSE bitmaps
; 7 ID number for control LOCAL hButn1 :DWORD
LOCAL hImage :DWORD
LOCAL hModule :DWORD
LOCAL wid :DWORD
LOCAL hgt :DWORD
LOCAL hBmpU :DWORD
LOCAL hBmpD :DWORD
LOCAL hBmpM :DWORD
LOCAL Rct :RECT
LOCAL wc :WNDCLASSEX invoke GetModuleHandle,NULL
mov hModule, eax invoke LoadBitmap,hModule,rnum1
mov hBmpU, eax
invoke LoadBitmap,hModule,rnum2
mov hBmpD, eax
invoke LoadBitmap, hModule, rnum3
mov hBmpM, eax jmp @F
Bmp_Button_Class db "Bmp_Button_Class",0
@@: mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc, offset MyBmpButnProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, 16
push hModule
pop wc.hInstance
mov wc.hbrBackground, COLOR_BTNFACE+1
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, offset Bmp_Button_Class
mov wc.hIcon, NULL
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor, eax
mov wc.hIconSm, NULL invoke RegisterClassEx, ADDR wc invoke CreateWindowEx,WS_EX_TRANSPARENT,
ADDR Bmp_Button_Class,NULL,
WS_CHILD or WS_VISIBLE,
topX,topY,100,100,hParent,ID,
hModule,NULL mov hButn1, eax invoke SetWindowLong,hButn1,0,hBmpU
invoke SetWindowLong,hButn1,4,hBmpD
invoke SetWindowLong,hButn1,8,hBmpM jmp @F
ButnImageClass db "STATIC",0
@@: invoke CreateWindowEx,0,
ADDR ButnImageClass,NULL,
WS_CHILD or WS_VISIBLE or SS_BITMAP,
0,0,0,0,hButn1,ID,
hModule,NULL mov hImage, eax invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hBmpU invoke GetWindowRect,hImage,ADDR Rct
invoke SetWindowLong,hButn1,12,hImage mov eax, Rct.bottom
mov edx, Rct.top
sub eax, edx
mov hgt, eax mov eax, Rct.right
mov edx, Rct.left
sub eax, edx
mov wid, eax invoke SetWindowPos,hButn1,HWND_TOP,0,0,wid,hgt,SWP_NOMOVE invoke ShowWindow,hButn1,SW_SHOW mov eax, hButn1 retMyBmpButton endpMyBmpButnProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD LOCAL hBmpU :DWORD
LOCAL hBmpD :DWORD
LOCAL hBmpM :DWORD
LOCAL hImage :DWORD
LOCAL hParent:DWORD
LOCAL ID :DWORD
LOCAL ptX :DWORD
LOCAL ptY :DWORD
LOCAL bWid :DWORD
LOCAL bHgt :DWORD
LOCAL Rct :RECT
LOCAL tme :TRACKMOUSEEVENT
LOCAL pt :POINT .data
cFlag dd 0 ; a GLOBAL variable for the "clicked" setting
hFlag dd 0 ; a GLOBAL variable for the "hover" setting .code
.if uMsg == WM_LBUTTONDOWN
invoke GetWindowLong,hWin,4
mov hBmpD, eax
invoke GetWindowLong,hWin,12
mov hImage, eax
invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hBmpD
invoke SetCapture,hWin
mov cFlag, 1 .elseif uMsg == WM_LBUTTONUP .if cFlag == 0
ret
.else
mov cFlag, 0
.endif invoke GetWindowLong,hWin,0
mov hBmpU, eax
invoke GetWindowLong,hWin,12
mov hImage, eax
invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hBmpU mov eax, lParam
cwde
mov ptX, eax
mov eax, lParam
rol eax, 16
cwde
mov ptY, eax invoke GetWindowRect,hWin,ADDR Rct mov eax, Rct.right
mov edx, Rct.left
sub eax, edx
mov bWid, eax mov eax, Rct.bottom
mov edx, Rct.top
sub eax, edx
mov bHgt, eax ; --------------------------------
; exclude button releases outside
; of the button rectangle from
; sending message back to parent
; --------------------------------
cmp ptX, 0
jle @F
cmp ptY, 0
jle @F
mov eax, bWid
cmp ptX, eax
jge @F
mov eax, bHgt
cmp ptY, eax
jge @F invoke GetParent,hWin
mov hParent, eax
invoke GetDlgCtrlID,hWin
mov ID, eax
invoke SendMessage,hParent,WM_COMMAND,ID,hWin @@: invoke ReleaseCapture ;each TrackMouseEvent only sends one message, so it must be recreated after each message
.elseif uMsg == WM_MOUSEMOVE
.if hFlag == 0
mov eax, hWin
mov tme.hwndTrack, eax
mov tme.cbSize, sizeof TRACKMOUSEEVENT
mov tme.dwFlags, TME_HOVER or TME_LEAVE
mov tme.dwHoverTime, 1; in ms
invoke TrackMouseEvent, addr tme
mov hFlag, 1
.endif
.elseif uMsg == WM_MOUSEHOVER
mov hFlag, 0
invoke GetWindowLong, hWin, 8
mov hBmpM, eax
invoke GetWindowLong, hWin, 12
mov hImage, eax
invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hBmpM
.elseif uMsg == WM_MOUSELEAVE
mov hFlag, 0
invoke GetWindowLong, hWin, 0
mov hBmpD, eax
invoke GetWindowLong, hWin, 12
mov hImage, eax
invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hBmpD
.endif invoke DefWindowProc,hWin,uMsg,wParam,lParam
retMyBmpButnProc endp

Hope somebody finds this useful ;)

Link to comment
Guest Tundra

Just noticed that if you move your mouse while clicking, the image resets.

Fix this by changing

	.elseif uMsg == WM_MOUSEHOVER
mov hFlag, 0
invoke GetWindowLong, hWin, 8
mov hBmpM, eax
invoke GetWindowLong, hWin, 12
mov hImage, eax
invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hBmpM
.elseif uMsg == WM_MOUSELEAVE
mov hFlag, 0
invoke GetWindowLong, hWin, 0
mov hBmpD, eax
invoke GetWindowLong, hWin, 12
mov hImage, eax
invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hBmpD

with

	.elseif uMsg == WM_MOUSEHOVER
mov hFlag, 0
.if cFlag == 0
invoke GetWindowLong, hWin, 8
mov hBmpM, eax
invoke GetWindowLong, hWin, 12
mov hImage, eax
invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hBmpM
.endif
.elseif uMsg == WM_MOUSELEAVE
mov hFlag, 0
.if cFlag == 0
invoke GetWindowLong, hWin, 0
mov hBmpU, eax
invoke GetWindowLong, hWin, 12
mov hImage, eax
invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hBmpU
.endif
.endif
Link to comment
Ok, I got it working. Here's the procedure I wrote for displaying bitmap buttons with a pressed image and a mouseover image. It's an edited version of masm32's BmpButton procedure.

Nice job Tundra :thumbsup: Now your all set to put this extended MyBmpButton code in your MASM library.

Thanks for sharing the snippet.

Ziggy

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...