Page 1 of 1
DetectStatusBar Events
Posted: Fri Sep 08, 2006 10:12 pm
by QuimV
Code updated For 5.20+
Hello,
Could anybody help me in order to detect the StatusBar events?
Here it is an example from fsw, but if we add a TreeGadget, the detection goes wrong.
Code: Select all
; Example Of A Statusbar Click Event
; (c) 2003 - By FSW
;
; Tested under WinXP
; do whatever you want with it
;
#Window = 10
#StatusbarFocus = 528
#StatusBar = 1
#Tree = 2
Procedure LoWord (var)
ProcedureReturn var & $FFFF
EndProcedure
Procedure MyWindowCallback(WindowID, Message, wParam, lParam)
Result = #PB_ProcessPureBasicEvents
wParamLo = LoWord(wParam)
lParamLo = LoWord(lParam)
;513 = $201
If Message = #StatusbarFocus ;#StatusbarFocus ;528 = $210 = #WM_PARENTNOTIFY
If wParamLo = #WM_LBUTTONDOWN And lParamLo < 270 ; 270 is the width of field 1
MessageRequester("Message", "Left Mouse Click In StatusBar Field 1. "+"MousePos: "+Str(lParamLo))
ElseIf wParamLo = 513 And lParamLo > 270 + 2 ; there is a BAR between the 2 fields...
MessageRequester("Message", "Left Mouse Click In StatusBar Field 2. "+"MousePos: "+Str(lParamLo))
ElseIf wParamLo = 516
MessageRequester("Message", "Right Mouse Click In StatusBar. "+"MousePos: "+Str(lParamLo))
EndIf
EndIf
ProcedureReturn Result
EndProcedure
If OpenWindow(#Window,0,0,355,180,"Statusbar Click",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateStatusBar(#StatusBar, WindowID(#Window))
AddStatusBarField(90)
StatusBarText(#StatusBar, 0, "Hello World!")
AddStatusBarField(270)
AddStatusBarField(80)
TreeGadget(#Tree,10,45,100,100,#PB_Tree_AlwaysShowSelection)
SendMessage_(GadgetID(#Tree),$111D,0,14675967)
SetWindowCallback(@MyWindowCallback())
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Thanks in advanced.
QuimV
Posted: Sat Sep 09, 2006 12:08 pm
by netmaestro
Looks like a message is getting processed as a statusbar click that shouldn't be. Other childwindows can generate #wm_parentnotify messages. You can always add a quick check to make sure the active child window is the status bar:
Code: Select all
; Example Of A Statusbar Click Event
; (c) 2003 - By FSW
;
; Tested under WinXP
; do whatever you want with it
;
#Window = 10
#StatusbarFocus = 528
#StatusBar = 1
#Tree = 2
Global Statusbar
Procedure.l LoWord (var.l)
ProcedureReturn var & $FFFF
EndProcedure
Procedure MyWindowCallback(WindowID, Message, wParam, lParam)
Result = #PB_ProcessPureBasicEvents
wParamLo = LoWord(wParam)
lParamLo = LoWord(lParam)
;513 = $201
If Message = #StatusbarFocus ;#StatusbarFocus ;528 = $210 = #WM_PARENTNOTIFY
If ChildWindowFromPoint_(WindowID(#Window),WindowMouseX(#Window),WindowMouseY(#Window)) = Statusbar
If wParamLo = #WM_LBUTTONDOWN And lParamLo < 270 ; 270 is the width of field 1
MessageRequester("Message", "Left Mouse Click In StatusBar Field 1. "+"MousePos: "+Str(lParamLo))
ElseIf wParamLo = 513 And lParamLo > 270 + 2 ; there is a BAR between the 2 fields...
MessageRequester("Message", "Left Mouse Click In StatusBar Field 2. "+"MousePos: "+Str(lParamLo))
ElseIf wParamLo = 516
MessageRequester("Message", "Right Mouse Click In StatusBar. "+"MousePos: "+Str(lParamLo))
EndIf
EndIf
EndIf
ProcedureReturn Result
EndProcedure
If OpenWindow(#Window,0,0,355,180,"Statusbar Click",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If CreateGadgetList(WindowID(#Window))
Statusbar = CreateStatusBar(#StatusBar, WindowID(#Window))
StatusBarText(#StatusBar, 0, "Hello World!")
AddStatusBarField(270)
AddStatusBarField(80)
TreeGadget(#Tree,10,45,100,100,#PB_Tree_AlwaysShowSelection)
SendMessage_(GadgetID(#Tree),$111D,0,14675967)
EndIf
SetWindowCallback(@MyWindowCallback())
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
A global var and ChildWindowFromPoint seems the most efficient solution as #WM_PARENTNOTIFY messages don't carry the childwindow identifier with them for buttondown events.
A somewhat cleaner solution imho would be to subclass the statusbar and then its callback is only catching events for it and there's no need to test for the right childwindow. I have to go out right now for a couple hours but I can post code for that if nobody beats me to it in the meantime.
Posted: Sat Sep 09, 2006 3:03 pm
by netmaestro
Here is the subclassed version, I think it's much cleaner this way:
Code: Select all
#Window = 10
#StatusBar = 1
#Tree = 2
Global OldStatusBar
Procedure.l LoWord (var.l)
ProcedureReturn var & $FFFF
EndProcedure
Procedure SubClassedStatusBar(hwnd, msg, wParam, lParam)
result = CallWindowProc_(OldStatusBar, hwnd, msg, wparam, lparam)
lParamLo = LoWord(lParam)
Select msg
Case #WM_LBUTTONDOWN
If lParamLo < 270 ; 270 is the width of field 1
MessageRequester("Message", "Left Mouse Click In StatusBar Field 1. "+"MousePos: "+Str(lParamLo))
ElseIf lParamLo > 270 + 2 ; there is a BAR between the 2 fields...
MessageRequester("Message", "Left Mouse Click In StatusBar Field 2. "+"MousePos: "+Str(lParamLo))
EndIf
Case #WM_RBUTTONDOWN
MessageRequester("Message", "Right Mouse Click In StatusBar. "+"MousePos: "+Str(lParamLo))
EndSelect
ProcedureReturn Result
EndProcedure
If OpenWindow(#Window,0,0,355,180,"Statusbar Click",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If CreateGadgetList(WindowID(#Window))
StatusBar = CreateStatusBar(#StatusBar, WindowID(#Window))
StatusBarText(#StatusBar, 0, "Hello World!")
AddStatusBarField(270)
AddStatusBarField(80)
TreeGadget(#Tree,10,45,100,100,#PB_Tree_AlwaysShowSelection)
SendMessage_(GadgetID(#Tree),$111D,0,14675967)
EndIf
OldStatusBar = SetWindowLong_(StatusBar, #GWL_WNDPROC, @SubclassedStatusBar())
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Re: DetectStatusBar Events
Posted: Tue Jan 20, 2026 12:01 pm
by BarryG
Updated netmaestro's code to work with the latest PureBasic:
Code: Select all
#Window=10
#StatusBar=1
Global StatusBarProc
Procedure SubClassedStatusBar(hWnd,Msg,wParam,lParam)
result=CallWindowProc_(StatusBarProc,hWnd,Msg,wParam,lParam)
lParamLo=lParam & $FFFF
Select Msg
Case #WM_LBUTTONDOWN
If lParamLo<100 ; 100 is the width of field 1
MessageRequester("Message","Left Mouse Click In StatusBar Field 1. "+"MousePos: "+Str(lParamLo))
ElseIf lParamLo>100+2 And lParamLo<270 ; there is a BAR between the 2 fields...
MessageRequester("Message","Left Mouse Click In StatusBar Field 2. "+"MousePos: "+Str(lParamLo))
EndIf
Case #WM_RBUTTONDOWN
MessageRequester("Message","Right Mouse Click In StatusBar. "+"MousePos: "+Str(lParamLo))
EndSelect
ProcedureReturn Result
EndProcedure
If OpenWindow(#Window,0,0,355,180,"Statusbar Click",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
StatusBar=CreateStatusBar(#StatusBar,WindowID(#Window))
AddStatusBarField(100)
StatusBarText(#StatusBar,0,"Field 1")
AddStatusBarField(270)
StatusBarText(#StatusBar,1,"Field 2")
StatusBarProc=SetWindowLongPtr_(StatusBar,#GWL_WNDPROC,@SubclassedStatusBar())
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
Re: DetectStatusBar Events
Posted: Tue Jan 20, 2026 12:25 pm
by jacdelad
If I'm not wrong, usually Windows controls react on button up. So button up events should be more "natural"?
Re: DetectStatusBar Events
Posted: Tue Jan 20, 2026 12:28 pm
by mk-soft
Why not as in the Code Questions already solved.
Only adapted with query of the StatusBarID (Handle).
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
If *nmm\hdr\hwndFrom = StatusBarID(0)
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
EndIf
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
Re: DetectStatusBar Events
Posted: Tue Jan 20, 2026 12:36 pm
by BarryG
mk-soft wrote: Tue Jan 20, 2026 12:28 pmWhy not as in the Code Questions already solved
Because as I said there:
BarryG wrote:See also netmaestro's code here, which shows the mouse X position in any field
So, some extra useful functionality if you want to click a specific position in a StatusBar field.
