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 :D

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 :D