Page 1 of 1

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

Posted: Tue Oct 24, 2023 12:54 pm
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

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

Posted: Tue Oct 24, 2023 2:22 pm
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

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

Posted: Tue Oct 24, 2023 2:43 pm
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

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

Posted: Tue Oct 24, 2023 6:39 pm
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

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

Posted: Wed Oct 25, 2023 4:11 am
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))

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

Posted: Wed Oct 25, 2023 8:24 pm
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

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

Posted: Wed Oct 25, 2023 9:47 pm
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)

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

Posted: Wed Oct 25, 2023 10:18 pm
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.)

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

Posted: Thu Oct 26, 2023 4:47 am
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

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

Posted: Thu Oct 26, 2023 8:01 am
by Jan2004
Thanks for help