Page 1 of 2
Button color mouseover issue
Posted: Fri Sep 24, 2021 7:22 am
by firace
I managed to put together the below code but when I add multiple buttons, the mouseover effect only works for one. Any ideas on how to fix this? Without adding global variables if possible.
Code: Select all
Procedure onMouseOver(GadgetNumber)
X = GadgetX(GadgetNumber, #PB_Gadget_WindowCoordinate)
Y = GadgetY(GadgetNumber, #PB_Gadget_WindowCoordinate)
Mx = WindowMouseX(0)
My = WindowMouseY(0)
GadgetHeight(GadgetNumber)
If Mx > X And Mx < (X + GadgetWidth(GadgetNumber)) And My > Y And My < (Y + GadgetHeight(GadgetNumber) )
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
Procedure WndCallback(hWnd, Msg, wParam, lParam)
Shared oldProc
Shared gadgetNumber
Select Msg
Case #WM_TIMER
If Not onMouseOver(gadgetNumber)
KillTimer_(hWnd, 123)
SetGadgetColor(gadgetNumber, #PB_Gadget_BackColor, $E1E1E1)
EndIf
Case #WM_MOUSEMOVE
If onMouseOver(gadgetNumber)
SetGadgetColor(gadgetNumber, #PB_Gadget_BackColor, $FCA3A3)
SetTimer_(hWnd, 123, 50, #Null) ;; 50ms timer
EndIf
EndSelect
ProcedureReturn CallWindowProc_(oldProc, hWnd, Msg, wParam, lParam)
EndProcedure
Procedure ButtonGadgetEx(g, x, y, w, h, text$="")
Shared oldProc
Shared gadgetNumber
gadgetNumber = g
ContainerGadget(g+100,x,y,w,h)
TextGadget(g,0,0,w,h, text$,#SS_CENTERIMAGE | #SS_CENTER | #SS_NOTIFY)
CloseGadgetList()
oldProc = SetWindowLongPtr_(GadgetID(g), #GWL_WNDPROC, @WndCallback())
SetGadgetColor(g,#PB_Gadget_BackColor,$E1E1E1)
EndProcedure
OpenWindow(0,0,0,510,280,"", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ButtonGadgetEx(1, 30, 220, 130, 40, "Button 1")
ButtonGadgetEx(2, 180, 220, 130, 40, "Button 2")
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 7:33 am
by Mijikai
You create two callbacks but only remember one oldProc so both go to the same destination.
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 7:38 am
by firace
Thanks, makes sense! I just tried to fix this with a shared oldproc() array, but no success so far:
Code: Select all
Dim oldProc(500)
Procedure onMouseOver(GadgetNumber)
X = GadgetX(GadgetNumber, #PB_Gadget_WindowCoordinate)
Y = GadgetY(GadgetNumber, #PB_Gadget_WindowCoordinate)
Mx = WindowMouseX(0)
My = WindowMouseY(0)
GadgetHeight(GadgetNumber)
If Mx > X And Mx < (X + GadgetWidth(GadgetNumber)) And My > Y And My < (Y + GadgetHeight(GadgetNumber) )
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
Procedure WndCallback(hWnd, Msg, wParam, lParam)
Shared oldProc()
Shared gadgetNumber
Select Msg
Case #WM_TIMER
If Not onMouseOver(gadgetNumber)
KillTimer_(hWnd, 123)
SetGadgetColor(gadgetNumber, #PB_Gadget_BackColor, $E1E1E1)
EndIf
Case #WM_MOUSEMOVE
If onMouseOver(gadgetNumber)
SetGadgetColor(gadgetNumber, #PB_Gadget_BackColor, $FCA3A3)
SetTimer_(hWnd, 123, 50, #Null) ;; 50ms timer
EndIf
EndSelect
ProcedureReturn CallWindowProc_(oldProc(gadgetNumber), hWnd, Msg, wParam, lParam)
EndProcedure
Procedure ButtonGadgetEx(g, x, y, w, h, text$="")
Shared oldProc()
Shared gadgetNumber
gadgetNumber = g
ContainerGadget(g+100,x,y,w,h)
TextGadget(g,0,0,w,h, text$, #SS_CENTER | #SS_NOTIFY)
CloseGadgetList()
oldProc(g) = GetWindowLongPtr_(GadgetID(g), #GWLP_WNDPROC)
SetWindowLongPtr_(GadgetID(g), #GWL_WNDPROC, @WndCallback())
SetGadgetColor(g,#PB_Gadget_BackColor,$E1E1E1)
EndProcedure
OpenWindow(0,0,0,510,280,"", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ButtonGadgetEx(1, 30, 220, 130, 40, "Button 1")
ButtonGadgetEx(2, 180, 220, 130, 40, "Button 2")
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 7:54 am
by Mijikai
The gadgetNumber has the same issue.
For no global/shared parameters u could use SetProp_() and GetProp_()
to link the needed parameters to the gadgets hwnd.
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 7:56 am
by ChrisR
Or add this perhaps in your WndCallback:
gadgetNumber = GetDlgCtrlID_(hWnd)
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 8:05 am
by firace
Problem solved! Thanks for both answers!
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 9:00 am
by RASHAD
Hi
Simple and effective approach
Code: Select all
OpenWindow(0,0,0,510,280,"", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
TextGadget(1, 30, 170, 130, 40, "Button 1",#SS_CENTERIMAGE | #SS_CENTER | #SS_NOTIFY)
SetGadgetColor(1, #PB_Gadget_BackColor, $E1E1E1)
TextGadget(2, 180, 170, 130, 40, "Button 2",#SS_CENTERIMAGE | #SS_CENTER | #SS_NOTIFY)
SetGadgetColor(2, #PB_Gadget_BackColor, $E1E1E1)
TextGadget(3, 30, 220, 130, 40, "Button 3",#SS_CENTERIMAGE | #SS_CENTER | #SS_NOTIFY)
SetGadgetColor(3, #PB_Gadget_BackColor, $E1E1E1)
TextGadget(4, 180, 220, 130, 40, "Button 4",#SS_CENTERIMAGE | #SS_CENTER | #SS_NOTIFY)
SetGadgetColor(4, #PB_Gadget_BackColor, $E1E1E1)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Quit = 1
Case #WM_MOUSEMOVE
GetCursorPos_ (@p.POINT)
ScreenToClient_ (WindowID(0), @p)
hWnd = ChildWindowFromPoint_ (WindowID(0), p\y<< 32 + p\x)
TRACK.TRACKMOUSEEVENT
TRACK\cbSize = SizeOf(TRACK)
TRACK\dwFlags = #TME_HOVER|#TME_LEAVE
TRACK\hwndTrack = hWnd
TRACK\dwHoverTime = 10
TrackMouseEvent_(@TRACK)
Case #WM_MOUSEHOVER
Gad = GetDlgCtrlID_(hWnd)
If Gad > 0
SetGadgetColor(gad, #PB_Gadget_BackColor, $FCA3A3)
EndIf
Case #WM_MOUSELEAVE
If Gad > 0
SetGadgetColor(gad, #PB_Gadget_BackColor, $E1E1E1)
EndIf
EndSelect
Until Quit = 1
Edit :Late again
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 9:07 am
by BarryG
Rashad, regarding this line:
Code: Select all
hWnd = ChildWindowFromPoint_ (WindowID(0), P\y<< 32 + p\x)
I learned some time ago in these forums that you can replace the last bit with PeekQ():
Code: Select all
hWnd = ChildWindowFromPoint_ (WindowID(0), PeekQ(p))
Would there be any reason NOT to use PeekQ() like that? It's safe? Seems to work fine?
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 9:18 am
by RASHAD
Hi BarryG
Yes you are absolutely right

Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 9:25 am
by firace
Thanks Rashad for the nice alternative approach!
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 9:26 am
by Mijikai
BarryG wrote: Fri Sep 24, 2021 9:07 am
...
Would there be any reason NOT to use PeekQ() like that? It's safe? Seems to work fine?
Maybe one is slower, even better would be to read the pos directly into a quad when calling GetCursorPos_().
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 4:23 pm
by Axolotl
And another solution:
With a structure like this
Code: Select all
Structure POINT_x64
StructureUnion
p.POINT
q.q
EndStructureUnion
EndStructure
you can do it as well
Code: Select all
Protected CursorPos.POINT_x64
; .. first get the cursor position
GetCursorPos_(CursorPos\p)
; .. then look for the window
Debug WindowFromPoint_(CursorPos\q)
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 4:30 pm
by netmaestro
Just send all the buttons to the same callback and use the hWnd parameter within the callback to choose whether or not to do the coloring. Or RASHAD's solution is a good one too.
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 4:55 pm
by RASHAD
@ firace
Thanks mate
@NM
Glad to read your posts even if it's from time to time
How are you doing mate(about your health I mean)
Re: Button color mouseover issue
Posted: Fri Sep 24, 2021 5:00 pm
by netmaestro
Thanks for asking! Moving a bit slower these days but I can still beat any c++ coder in an arm wrestle
