Im having trouble finding out how to recieve the WM_NOTIFY message for my ownerdrawn buttons, I need it to find out when the mouse is over the button. I've set the button as NOTIFY also.
WM_NOTIFY doesn't get sent to my window when I use normal buttons either until I add the manifest file to the resource, which is odd. but I want WM_NOTIFY for my ownerdrawn buttons
maybe WM_NOTIFY isn't being sent to my main window when the button is ownerdrawn, and its being sent to the button itself. which means I'd have to set a custom wndproc for all my buttons (i'd prefer not doing it that way)
If someone can tell me a way to know if the mouse is over a button and when its left the button other than WM_NOTIFY then I'd use it instead.
Thanks in advance,
Fab
Posting your code might be helpful (it beats guessing.)
Instead of setting a custom wndproc for all your buttons, you could subclass the button class and create your buttons as this class - which would have them all ownerdrawn by the same proc. But this doesn't really solve your original problem - just sidesteps it :wink
An alternative to wm_notify, could be wm_mousemove, but this would require checking the cursor position against each of your buttons every time the mouse moves - probably not the best idea.
Code.. post code :toothy
Creating the button with BS_NOTIFY sends notification messages through WM_COMMAND, not WM_NOTIFY. However, it still goes to the parent window.
You can check if the mouse is over your button using something like this:
invoke GetCursorPos, ADDR mouse_pos
invoke GetWindowRect, hButton, ADDR button_rect
invoke PtInRect, ADDR button_rect, ADDR mouse_pos
.if(eax != 0)
; mouse is over button
.else
; mouse is not over button
.endif
Also, there is an itemState parameter in the DRAWITEMSTRUCT structure passed in a WM_DRAWITEM message. This parameter may contain the ODS_HOTLIGHT constant:
Quote from: MSDNODS_HOTLIGHT
Windows 98/Me, Windows 2000/XP: The item is being hot-tracked, that is, the item will be highlighted when the mouse is on the item.
This obviously isn't a complete description, so it'll need some experimentation, but it may be a start :U
Cheers,
Zooba
Thank you both for the helpful info :U
The reason I wanted to use WM_NOTIFY was for the BCN_HOTIMEMCHANGE notification.
on msdn
Quote
The BCN_HOTITEMCHANGE message notifies the button control owner that the mouse is entering or leaving the client area of the button control. The button control sends this notification in the form of a WM_NOTIFY message.
that is exactly what I needed to use
but later down the page
Quote
Note To use this API, you must provide a manifest specifying Comclt32.dll version 6.0. For more information on manifests, see Using Windows XP Visual Styles.
and I need my program to work in win98 (and Comclt32.dll 6.0 isn't distributable)
Even when I added the manifest ownerdrawn buttons didn't recieve the BCN_HOTITEMCHANGE WM_NOTIFY message, only normal ones did.
so like your suggestions I used WM_MOUSEMOVE instead
but I still needed to find out when the mouse left the button window without having to use the surrounding/underlying window/s recieving a WM_MOUSEMOVE message to know when the mouse is off the button (because someone could move the mouse fast enough to leave the entire window without making WM_MOUSEMOVE trigger in the surrounding areas of the button)
so I cominbed TrackMouseEvent with the TME_LEAVE and the WM_MOUSEMOVE, and made some really bad code on how to track the mouse for each ownerdrawn button
also ODS_HOTLIGHT did not work for my ownerdrawn buttons, with or without a manifest file
this isn't a copy of my working code, I just wrote it out of memory to give you an idea of what Im trying to do, so it might have LOTS of mistakes
.data?
hWnd DWORD ?
Extra struct
hOldproc DWORD ?
IsMouseOver DWORD ?
Extra ends
.code
DialogProc proc uses esi,edi,ebx hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
.if uMsg == WM_INITDIALOG
m2m hWnd,hWin
mov edi,1001 ;first ownerdrawn button ID
.while edi<=1100
invoke GetDlgItem,hWin,edi ;get hWnd for it
mov esi,eax
invoke GlobalAlloc,GMEM_FIXED or GMEM_ZEROINIT,SIZEOF Extra
mov ebx,eax
invoke GetWindowLong,esi,GWL_WNDPROC ;get it now before I change it
mov [ebx].Extra.hOldproc,eax
invoke SetWindowLong,esi,GWL_USERDATA,ebx ;set userdata to Alloced memory
invoke SetWindowLong,esi,GWL_WNDPROC,addr proc_MYBUTTON ;subclass button
inc edi
.endw ;loop and do all 100 buttons
.elseif uMsg == WM_DRAWITEM
mov esi,lParam
assume esi:PTR DRAWITEMSTRUCT
; I do my button drawing here
; '.if [esi].itemstate & ODS_HOTLIGHT' doesn't work for me :(
; and it doesn't send out a WM_DRAWITEM every time I do a mouse over either
; so I use the following
invoke GetWindowLong,[esi].hwndItem,GWL_USERDATA
.if ([eax].Extra.IsMouseOver) && (eax)
;draw it like mouse is over button
.else
;draw it normally
.endif
mov eax,TRUE
assume esi:NOTHING
.elseif uMsg == WM_CLOSE
invoke EndDialog,hWnd
.else
xor eax,eax
.endif
ret
DialogProc endp
proc_MYBUTTON proc hCtl:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
LOCAL TME:TRACKMOUSEEVENT
.if uMsg == WM_MOUSEMOVE
invoke GetWindowLong,hCtl,GWL_USERDATA
.if [eax].Extra.IsMouseOver == FALSE ;dont want to redraw the button every time the mouse moves
mov [eax].Extra.IsMouseOver,TRUE
m2m TME.cbSize,SIZEOF TME
m2m TME.dwFlags,TME_LEAVE
m2m TME.hwndTrack,hCtl
m2m TME.dwHoverTime,0
invoke TrackMouseEvent,addr TME
invoke RedrawWindow,hCtl,NULL,NULL,TRUE ;have to manually set off the WM_DRAWITEM notification
.endif
.elseif uMsg == WM_MOUSELEAVE
.if [eax].Extra.IsMouseOver == TRUE
mov [eax].Extra.IsMouseOver,FALSE
invoke RedrawWindow,hCtl,NULL,NULL,TRUE ;fires a WM_DRAWITEM
.endif
.endif
invoke GetWindowLong,hCtl,GWL_USERDATA
invoke CallWindowProc,[eax].Extra.hOldproc,hCtl,uMsg,wParam,lParam
ret
proc_MYBUTTON endp
Is there a better way to make my buttons know if the mouse if over them or not than what I've attempted?
Thanks again,
Fab :eek