One button with a hand cursor and the other a classic button with an arrow

Windows specific forum
Jan2004
Enthusiast
Enthusiast
Posts: 163
Joined: Fri Jan 07, 2005 7:17 pm

One button with a hand cursor and the other a classic button with an arrow

Post by Jan2004 »

How can I improve this code so that a hand cursor appears over one button and a classic cursor (arrow) appears over the other button? In my code, even though "SetClassLongPtr_(GadgetID(1)" is set to only for one button, the hand cursor appears over both buttons.

Code: Select all

EnableExplicit

If OpenWindow(0, 0, 0, 500, 170, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(1, 20, 50, 200, 28, "Button with hand cursor", 0)
   ButtonGadget(2, 252, 50, 230, 28, "Button without hand cursor", 0)
  
  SetClassLongPtr_(GadgetID(1), #GCL_HCURSOR, LoadCursor_(0, #IDC_HAND))
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: One button with a hand cursor and the other a classic button with an arrow

Post by chi »

quick & dirty:

Code: Select all

EnableExplicit

If OpenWindow(0, 0, 0, 500, 170, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    
  ButtonGadget(2, 252, 50, 230, 28, "Button without hand cursor", 0)

  Define Button.WNDCLASS
  GetClassInfo_(0, "Button", Button)
  Button\hCursor = LoadCursor_(0, #IDC_HAND)
  Button\style & ~#CS_GLOBALCLASS
  RegisterClass_(@Button)  
  
  ButtonGadget(1, 20, 50, 200, 28, "Button with hand cursor", 0)
  SetWindowPos_(GadgetID(1), #HWND_TOP, 0, 0, 0, 0, #SWP_NOSIZE|#SWP_NOMOVE|#SWP_NOACTIVATE)

  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
Et cetera is my worst enemy
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4953
Joined: Sun Apr 12, 2009 6:27 am

Re: One button with a hand cursor and the other a classic button with an arrow

Post by RASHAD »

Code: Select all

EnableExplicit

If OpenWindow(0, 0, 0, 500, 170, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(1, 20, 50, 200, 28, "Button with hand cursor", 0)
  ButtonGadget(2, 252, 50, 230, 28, "Button without hand cursor", 0)
  
  Define.l HandCur ,WaitCur 
  HandCur  = LoadCursor_(0, #IDC_HAND)
  WaitCur  = LoadCursor_(0, #IDC_WAIT)  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        End
        
      Case #WM_MOUSEMOVE
        Select ChildWindowFromPoint_(WindowID(0),WindowMouseY(0) << 32 + WindowMouseX(0)) 
          Case GadgetID(1)
            SetClassLongPtr_(GadgetID(1), #GCL_HCURSOR, HandCur)
            
          Case GadgetID(2)
            SetClassLongPtr_(GadgetID(2), #GCL_HCURSOR, WaitCur)      
        EndSelect      
    EndSelect
  ForEver
EndIf
Egypt my love
Jan2004
Enthusiast
Enthusiast
Posts: 163
Joined: Fri Jan 07, 2005 7:17 pm

Re: One button with a hand cursor and the other a classic button with an arrow

Post by Jan2004 »

Thank you, dear colleagues, for your comprehensive tips.
Can this theory, I received from you, also be extended to ImageGadget, especially if 3 states are used?
These are the solutions commonly used by a disliked here on the forum antivirus , program - Eset. (I don't like Eset either, because it interferes every now and then (in this sense, it's a virus), but I decided to survive until the end of the paid subscription). However, I like Eset's graphical interface solutions.
Below is analyzed code, with links to graphic files.

Code: Select all

;If Procedure IsMouseOver is in Enumeration there are problems
Procedure IsMouseOver(hWnd) 
    GetWindowRect_(hWnd,r.RECT) 
    GetCursorPos_(p.POINT) 
    Result = PtInRect_(r,p\y << 32 + p\x) 
    ProcedureReturn Result 
  EndProcedure 
EnableExplicit


Enumeration
#ButtonImage_fp 
#ButtonImage_fp_hover
#ButtonImage_fp_pressed

#ButtonImage_sp
EndEnumeration

Define fp
Define fp_hover
Define fp_pressed 
Define sp

Define hWnd
Global r.RECT
Global p.POINT

Define Result
Define Quit

fp = LoadImage(3,"first_picture1.bmp")
fp_hover = LoadImage(4,"first_picture_hover1.bmp")
fp_pressed = LoadImage(5,"first_picture_pressed1.bmp")

sp = LoadImage(6,"second_picture2.bmp")


  

If OpenWindow(0, 0, 0, 500, 310, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
 ; ButtonImageGadget(#ButtonImage_fp , 20, 70, 200, 200,ImageID(3))
  ;SetGadgetAttribute(#ButtonImage_fp,  #PB_Button_PressedImage, ImageID(5))
  
   ImageGadget(#ButtonImage_sp, 280, 70, 200, 200,ImageID(6))
  
    
ButtonGadget(2, 280, 20, 200, 28, "Button without hand cursor")
 

  Define Button.WNDCLASS
  GetClassInfo_(0, "Button", Button)
  Button\hCursor = LoadCursor_(0, #IDC_HAND)
  Button\style & ~#CS_GLOBALCLASS
  RegisterClass_(@Button)  
  ButtonGadget(1, 20, 20, 200, 28, "Button with hand cursor", 0)
  SetWindowPos_(GadgetID(1), #HWND_TOP, 0, 0, 0, 0, #SWP_NOSIZE|#SWP_NOMOVE|#SWP_NOACTIVATE)
  
  ImageGadget(#ButtonImage_fp , 20, 70, 200, 200,ImageID(3))

  
  Repeat
          
  Select WaitWindowEvent()
      
      Case #PB_Event_CloseWindow
            Quit = 1
            

        
              Case #WM_MOUSEMOVE 
              If IsMouseOver(GadgetID(#ButtonImage_fp)) 
                  SetGadgetState(#ButtonImage_fp,ImageID(4))
              Else
                  ;#ButtonImage_sp
                  SetGadgetState(#ButtonImage_fp,ImageID(3))
              EndIf
              
      Case #WM_LBUTTONDOWN
              If IsMouseOver(GadgetID(#ButtonImage_fp))
                  ;Pressed(10)
                  SetGadgetState(#ButtonImage_fp,ImageID(5))
              Else
                  SetGadgetState(#ButtonImage_fp,ImageID(3))
                EndIf  
                
                
      Case #PB_Event_CloseWindow
       
    EndSelect
    
Until Quit = 1
End


EndIf
Here are graphic files:
https://lokus.com.pl/hand_cursor.zip
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: One button with a hand cursor and the other a classic button with an arrow

Post by chi »

Jan2004 wrote: Tue Oct 24, 2023 6:39 pm Can this theory, I received from you, also be extended to ImageGadget, especially if 3 states are used?
Sure, just replace the last ImageGadget with following code...

Code: Select all

  Define StaticWC.WNDCLASS
  GetClassInfo_(0, "Static", StaticWC)
  StaticWC\hCursor = LoadCursor_(0, #IDC_HAND)
  StaticWC\style & ~#CS_GLOBALCLASS
  RegisterClass_(@StaticWC)    
  
  ImageGadget(#ButtonImage_fp , 20, 70, 200, 200,ImageID(3))
Et cetera is my worst enemy
Jan2004
Enthusiast
Enthusiast
Posts: 163
Joined: Fri Jan 07, 2005 7:17 pm

Re: One button with a hand cursor and the other a classic button with an arrow

Post by Jan2004 »

Chi, thank you for the code. What should I do to prevent the hand cursor from appearing above subsequent buttons when your code is earlier, before the buttons over which the normal cursor, i.e. an arrow, is to be placed? Details will be visible after running the code below:

Code: Select all

;;If Procedure IsMouseOver is in Enumeration there are problems
Procedure IsMouseOver(hWnd) 
    GetWindowRect_(hWnd,r.RECT) 
    GetCursorPos_(p.POINT) 
    Result = PtInRect_(r,p\y << 32 + p\x) 
    ProcedureReturn Result 
  EndProcedure 
EnableExplicit


Enumeration
#ButtonImage_fp 
#ButtonImage_fp_hover
#ButtonImage_fp_pressed

#ButtonImage_sp
EndEnumeration

Define fp
Define fp_hover
Define fp_pressed 
Define sp

Define hWnd
Global r.RECT
Global p.POINT

Define Result
Define Quit

fp = LoadImage(3,"first_picture1.bmp")
fp_hover = LoadImage(4,"first_picture_hover1.bmp")
fp_pressed = LoadImage(5,"first_picture_pressed1.bmp")

sp = LoadImage(6,"second_picture2.bmp")


  

If OpenWindow(0, 0, 0, 500, 310, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  
;   IF THERE ARE BUTTONS HERE AND NOT AT THE BOTTOM, EVERYTHING WORKS FINE
;   ImageGadget(#ButtonImage_sp, 280, 70, 200, 200,ImageID(6))
;   ButtonGadget(2, 280, 20, 200, 28, "Button without hand cursor")

  
;   THE CODE FOR CURSORS IS BEFORE THE BUTTONS FOR WHICH THERE SHOULD BE A NORMAL CURSOR
  Define Button.WNDCLASS
  GetClassInfo_(0, "Button", Button)
  Button\hCursor = LoadCursor_(0, #IDC_HAND)
  Button\style & ~#CS_GLOBALCLASS
  RegisterClass_(@Button)  
  
  ButtonGadget(1, 20, 20, 200, 28, "Button with hand cursor", 0)
  SetWindowPos_(GadgetID(1), #HWND_TOP, 0, 0, 0, 0, #SWP_NOSIZE|#SWP_NOMOVE|#SWP_NOACTIVATE)
  
  
  Define StaticWC.WNDCLASS
  GetClassInfo_(0, "Static", StaticWC)
  StaticWC\hCursor = LoadCursor_(0, #IDC_HAND)
  StaticWC\style & ~#CS_GLOBALCLASS
  RegisterClass_(@StaticWC)    
  
  ImageGadget(#ButtonImage_fp , 20, 70, 200, 200,ImageID(3))
  
  
  ;-------------------------------------------------------------
  ;  the buttons are behind the code on the hand cursor
ImageGadget(#ButtonImage_sp, 280, 70, 200, 200,ImageID(6))
ButtonGadget(2, 280, 20, 200, 28, "Button without hand cursor")
 
  
  Repeat
          
  Select WaitWindowEvent()
      
      Case #PB_Event_CloseWindow
            Quit = 1
        
              Case #WM_MOUSEMOVE 
              If IsMouseOver(GadgetID(#ButtonImage_fp)) 
                  SetGadgetState(#ButtonImage_fp,ImageID(4))
              Else
                  
                  SetGadgetState(#ButtonImage_fp,ImageID(3))
              EndIf
              
      Case #WM_LBUTTONDOWN
              If IsMouseOver(GadgetID(#ButtonImage_fp))
              
                  SetGadgetState(#ButtonImage_fp,ImageID(5))
              Else
                  SetGadgetState(#ButtonImage_fp,ImageID(3))
                EndIf  
                
                
      Case #PB_Event_CloseWindow
       
    EndSelect
    
Until Quit = 1
End
EndIf
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: One button with a hand cursor and the other a classic button with an arrow

Post by chi »

That's the dirty part ;)... You can do it only at the end of the initialization of your "normal" gadgets. After you change the class, all subsequently created gadgets will have the new hand cursor.
If you want the TAB key to work properly, use SetWindowPos_(GadgetID(...), #HWND_TOP or GadgetID(...), 0, 0, 0, 0, #SWP_NOSIZE|#SWP_NOMOVE|#SWP_NOACTIVATE)
Et cetera is my worst enemy
Jan2004
Enthusiast
Enthusiast
Posts: 163
Joined: Fri Jan 07, 2005 7:17 pm

Re: One button with a hand cursor and the other a classic button with an arrow

Post by Jan2004 »

Do you know what is the cause of this problem? Who is to blame. (Years ago, JavaScript wouldn't open on my website in Chrome. I reported it to Google and they fixed the Chrome browser.)
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: One button with a hand cursor and the other a classic button with an arrow

Post by netmaestro »

Code: Select all

Global tme.TRACKMOUSEEVENT
Global hand = LoadCursor_(0, #IDC_HAND), arrow = LoadCursor_(0, #IDC_ARROW)

Procedure HoverProc(hWnd, Msg, wParam, lParam)
  oldproc = GetProp_(hWnd, "oldproc")
  Select Msg
    Case #WM_NCDESTROY
      RemoveProp_(hWnd, "oldproc")
      
    Case #WM_MOUSEMOVE
      TrackMouseEvent_(@tme)
      SetCursor_(hand)
 
    Case #WM_MOUSEHOVER   
       TrackMouseEvent_(@tme)
 
     Case #WM_MOUSELEAVE
        SetCursor_(arrow)

  EndSelect
  ProcedureReturn CallWindowProc_(oldproc, hWnd, Msg, wParam, lParam)
EndProcedure

OpenWindow(0,0,0,320,240,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ButtonGadget(1,30,20,120,30,"Hand Button")
ButtonGadget(2,160,20,120,30,"Arrow Button")

SetProp_(GadgetID(1),"oldproc",SetWindowLongPtr_(GadgetID(1),#GWL_WNDPROC,@HoverProc()))

With tme
  \cbSize=SizeOf(TRACKMOUSEEVENT)
  \dwFlags = #TME_LEAVE|#TME_HOVER 
  \hwndTrack = GadgetID(1)
EndWith

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
BERESHEIT
Jan2004
Enthusiast
Enthusiast
Posts: 163
Joined: Fri Jan 07, 2005 7:17 pm

Re: One button with a hand cursor and the other a classic button with an arrow

Post by Jan2004 »

Thanks for help
Post Reply