Button color mouseover issue

Just starting out? Need help? Post your questions and find answers here.
firace
Addict
Addict
Posts: 899
Joined: Wed Nov 09, 2011 8:58 am

Button color mouseover issue

Post 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 
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Button color mouseover issue

Post by Mijikai »

You create two callbacks but only remember one oldProc so both go to the same destination.
firace
Addict
Addict
Posts: 899
Joined: Wed Nov 09, 2011 8:58 am

Re: Button color mouseover issue

Post 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 
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Button color mouseover issue

Post 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.
User avatar
ChrisR
Addict
Addict
Posts: 1127
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Button color mouseover issue

Post by ChrisR »

Or add this perhaps in your WndCallback:
gadgetNumber = GetDlgCtrlID_(hWnd)
firace
Addict
Addict
Posts: 899
Joined: Wed Nov 09, 2011 8:58 am

Re: Button color mouseover issue

Post by firace »

Problem solved! Thanks for both answers!
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: Button color mouseover issue

Post 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
Egypt my love
BarryG
Addict
Addict
Posts: 3293
Joined: Thu Apr 18, 2019 8:17 am

Re: Button color mouseover issue

Post 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?
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: Button color mouseover issue

Post by RASHAD »

Hi BarryG
Yes you are absolutely right :D
Egypt my love
firace
Addict
Addict
Posts: 899
Joined: Wed Nov 09, 2011 8:58 am

Re: Button color mouseover issue

Post by firace »

Thanks Rashad for the nice alternative approach!
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Button color mouseover issue

Post 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_().
Axolotl
Enthusiast
Enthusiast
Posts: 435
Joined: Wed Dec 31, 2008 3:36 pm

Re: Button color mouseover issue

Post 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)      
 
Mostly running PureBasic <latest stable version and current alpha/beta> (x64) on Windows 11 Home
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Button color mouseover issue

Post 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.
BERESHEIT
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: Button color mouseover issue

Post 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)
Egypt my love
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Button color mouseover issue

Post by netmaestro »

Thanks for asking! Moving a bit slower these days but I can still beat any c++ coder in an arm wrestle :D
BERESHEIT
Post Reply