Detect RMB on statusbar

Just starting out? Need help? Post your questions and find answers here.
User avatar
Lord
Addict
Addict
Posts: 911
Joined: Tue May 26, 2009 2:11 pm

Detect RMB on statusbar

Post by Lord »

Hi!

Short question: Is there an easier (or even better a correct) way to detect a RMB down or RMB up on a statusbar?
I came up with this:

Code: Select all

EnableExplicit 

Define sbh
Define Event

Procedure WinCallback(hWnd, uMsg, wParam, lParam) 
  Select uMsg
    Case 528
      AddGadgetItem(1, -1, "RMB")
      If WindowMouseY(1) > GadgetHeight(1)
        AddGadgetItem(1, -1, "Statusbar") 
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure

If OpenWindow(1, 0, 0, 400, 200, "Window Caption", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CreateStatusBar(1, WindowID(1))
  sbh=StatusBarHeight(1)
  EditorGadget(1, 0, 0, 400, 200-sbh)
  
  SetWindowCallback(@WinCallback())
  
  Repeat 
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_CloseWindow 
        Break
      Default
    EndSelect
  ForEver 
EndIf 
I can't find the a name for the uMsg '528' which I got by try and error for aRMB down.

Any ideas?

Thanks in advance for reading.

Lord
Image
Axolotl
Addict
Addict
Posts: 921
Joined: Wed Dec 31, 2008 3:36 pm

Re: Detect RMB on statusbar

Post by Axolotl »

From my list of windows messages, I think that 528 might by #WM_PARENTNOTIFY.

Or you can use The Magic Number Database to find constants and numbers.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Axolotl
Addict
Addict
Posts: 921
Joined: Wed Dec 31, 2008 3:36 pm

Re: Detect RMB on statusbar

Post by Axolotl »

You can do it like this:

Code: Select all

; Self made clickable statusbar 
; written by Axolotl 
; 
Procedure WinCallback(Hwnd, UMsg, WParam, LParam) 
  Protected field, *nmm.NMMOUSE 

  Select UMsg 
    Case #WM_NOTIFY 
      *nmm = LParam 
      field = *nmm\dwItemSpec   ; zero-based index of the fields 
      ; field is -2 for an undefined area as field :) 
      Select *nmm\hdr\code 
        Case #NM_CLICK    : Debug "Left Click on " + field 
        Case #NM_DBLCLK   : Debug "Left Double Click on " + field 
        Case #NM_RCLICK   : Debug "Right Click on " + field 
        Case #NM_RDBLCLK  : Debug "Right Double Click on " + field 
      EndSelect  
  EndSelect 
  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

If OpenWindow(0, 100, 150, 300, 100, "PureBasic - StatusBar Example", #PB_Window_SystemMenu | #PB_Window_SizeGadget)

  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(100)
    AddStatusBarField(50)
    AddStatusBarField(100)
  EndIf

  StatusBarText(0, 0, "Area 1")
  StatusBarText(0, 1, "Area 2", #PB_StatusBar_BorderLess)
  StatusBarText(0, 2, "Area 3", #PB_StatusBar_Right | #PB_StatusBar_Raised)

  SetWindowCallback(@WinCallback(), 0) 
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 5027
Joined: Sun Apr 12, 2009 6:27 am

Re: Detect RMB on statusbar

Post by RASHAD »

Hi Lord

Code: Select all

EnableExplicit 

Define sbh
Define Event

Procedure WinCallback(hWnd, uMsg, wParam, lParam) 
  Select uMsg
    Case #WM_CONTEXTMENU
      AddGadgetItem(1, -1, "RMB")
      If wParam = StatusBarID(1)
        AddGadgetItem(1, -1, "Statusbar") 
      EndIf 
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure

If OpenWindow(1, 0, 0, 400, 200, "Window Caption", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CreateStatusBar(1, WindowID(1))
  sbh=StatusBarHeight(1)
  EditorGadget(1, 0, 0, 400, 200-sbh)
  
  SetWindowCallback(@WinCallback())
  
  Repeat 
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_CloseWindow 
        Break
      Default
    EndSelect
  ForEver 
EndIf 
Egypt my love
User avatar
Lord
Addict
Addict
Posts: 911
Joined: Tue May 26, 2009 2:11 pm

Re: Detect RMB on statusbar

Post by Lord »

Hi!

Thank you Axolotl and RASHAD for replying to my request.

Both examples give me the requested behaviour.
I think I will go with Axolotl's example as it gives me more variations of mousebutton events on statusbar which I can use in the future.

Greetings

Lord
Image
BarryG
Addict
Addict
Posts: 4312
Joined: Thu Apr 18, 2019 8:17 am

Re: Detect RMB on statusbar

Post by BarryG »

Axolotl wrote: Mon Jan 19, 2026 5:27 pmuse The Magic Number Database to find constants and numbers
Nice! Bookmarked. Thanks.

See also netmaestro's code here, which shows the mouse X position in any field: viewtopic.php?p=650331#p650331
Axolotl
Addict
Addict
Posts: 921
Joined: Wed Dec 31, 2008 3:36 pm

Re: Detect RMB on statusbar

Post by Axolotl »

Okay than, challenge accepted. :)

Due to the demand for mouse positioning and the solutions in the other thread, here is another version with a subclass solution and more information
(full API for enthusiasts).
Here you have many options to get the information you need.

Code: Select all

; Self made clickable statusbar Version 2 -- Subclass and PostEvent 
; written by Axolotl 
; 
EnableExplicit 

Enumeration EWindow 1 
  #WND_Main 
EndEnumeration 

Enumeration EGadget 1 
  #GDT_txtMousePos 
  #GDT_txtInfo  
  ; ... 
EndEnumeration 

Enumeration EStatusbar 1 
  #STB_Main 
EndEnumeration 

Enumeration EEvent #PB_Event_FirstCustomValue   ; Solution 1 => custom event 
  #EVT_Statusbar
EndEnumeration 

;-- Import "Comctl32.lib"  
Import "Comctl32.lib"  ;{ <<< from (latest) Comctl32.dll  >>>
  ; use the PureBasic Syntax (Windows API procedures using trailing underscore) 
  ; 
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    SetWindowSubclass_(hWnd, *fnSubclass, uIdSubclass, dwRefData)  As "SetWindowSubclass" 
    GetWindowSubclass_(hWnd, *fnSubclass, uIdSubclass, *dwRefData) As "GetWindowSubclass"
    RemoveWindowSubclass_(hWnd, *fnSubclass, uIdSubclass)          As "RemoveWindowSubclass"
    DefSubclassProc_(hWnd, uMsg, wParam, lParam)                   As "DefSubclassProc"
  CompilerElse
    SetWindowSubclass_(hWnd, *fnSubclass, uIdSubclass, dwRefData)  As "_SetWindowSubclass@16" 
    GetWindowSubclass_(hWnd, *fnSubclass, uIdSubclass, *dwRefData) As "_GetWindowSubclass@16"
    RemoveWindowSubclass_(hWnd, *fnSubclass, uIdSubclass)          As "_RemoveWindowSubclass@12"
    DefSubclassProc_(hWnd, uMsg, wParam, lParam)                   As "_DefSubclassProc@16" 
  CompilerEndIf

EndImport ;} End of import "Comctl32.lib" 


Procedure StatusbarSubclassProc(hWnd, uMsg, wParam, lParam, uIdSubclass, dwRefData) 
  Protected index, found, nbFields, tmp, pt.POINT, rc.RECT, Dim borders.l(3)   
  
  Select uMsg 
    Case #WM_NCDESTROY ; clean up 
      RemoveWindowSubclass_(hWnd, @StatusbarSubclassProc(), uIdSubclass)  

    Case #WM_MOUSEMOVE 
      ; this gadget support is for debugging reasons 
      SetGadgetText(#GDT_txtMousePos, "MousePos: " + Str(lParam & $FFFF) + ", " + Str(lParam >> 16 & $FFFF)) 

    Case #WM_LBUTTONDOWN                                            ;: Debug "WM_LBUTTONDOWN  " 
      If GetCursorPos_(@pt) And ScreenToClient_(hWnd, @pt) 

        If SendMessage_(hWnd, #SB_GETBORDERS, 0, @borders()) ; array that has three elements => width of horizontal, vertical and border between rectangles. 
        EndIf 
        nbFields = SendMessage_(hWnd, #SB_GETPARTS, 0, 0) ; retrieve the current number of Fields 
        If nbFields 
          found = -1 ; or -2 
          For index = 0 To nbFields - 1 
            tmp = pt\x + (index * borders(2)) 
            If SendMessage_(hWnd, #SB_GETRECT, index, @rc) And tmp >= rc\left And tmp <= rc\right 
              found = index 
              Break 
            EndIf 
          Next index 
          ; custom event (dwRefDate == Event and uIdSubclass == Window)  
          PostEvent(dwRefData, uIdSubclass, found)        ; use Object as Field-Number 
        EndIf 
      EndIf 
      ProcedureReturn 1                                 ; if the message is done 
      
;   Case #WM_RBUTTONDOWN                                                       :Debug "WM_RBUTTONDOWN"  
; ; copy the code from above for right mouse button if you need it. 
;     ProcedureReturn 1                                 ; if the message is done 
      
  EndSelect 
  ProcedureReturn DefSubclassProc_(hWnd, uMsg, wParam, lParam) 
EndProcedure 

Procedure Main() 
  Protected fieldNumber 
  
  If OpenWindow(#WND_Main, 100, 150, 320, 100, "PureBasic - StatusBar Example", #PB_Window_SystemMenu | #PB_Window_SizeGadget| #PB_Window_ScreenCentered)
    TextGadget(#GDT_txtMousePos, 8, 8, 304, 20, "") 
    
    TextGadget(#GDT_txtInfo, 8, 32, 304, 20, "") 

    If CreateStatusBar(#STB_Main, WindowID(#WND_Main)) 
      AddStatusBarField(100)
      AddStatusBarField(50)
      AddStatusBarField(100)
    EndIf
  
    StatusBarText(#STB_Main, 0, "Area 1")
    StatusBarText(#STB_Main, 1, "Area 2");, #PB_StatusBar_BorderLess)
    StatusBarText(#STB_Main, 2, "Area 3", #PB_StatusBar_Right | #PB_StatusBar_Raised)
  
    ; Subclass with 
    ;   dwRefDate == Event 
    ;   uIdSubclass == Window 
    SetWindowSubclass_(StatusBarID(#STB_Main), @StatusbarSubclassProc(), #WND_Main, #EVT_Statusbar) 

    Repeat
      Select WaitWindowEvent() 
        Case #PB_Event_CloseWindow
          Break 
        
        Case #EVT_Statusbar  ; use custom event 
          fieldNumber = EventGadget() ; see above 
          If fieldNumber = -1 
            SetGadgetText(#GDT_txtInfo, "Clicked on Field Number == Outside the Fields") 
          Else 
            SetGadgetText(#GDT_txtInfo, "Clicked on Field Number == " + Str(fieldNumber)) 
          EndIf 
      EndSelect 
    ForEver
  EndIf 
  ProcedureReturn 0 
EndProcedure 

End Main() 
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Post Reply