Page 1 of 1
[SOLVED] Events in system tray
Posted: Wed Sep 04, 2024 11:41 am
by ZX80
Hi, all.
Sorry if this is a dumb question and if I missed this, but I can't seem to find a solution. My question sound as:
How can I forcefully clear the event queue ? I'm getting a lot of mouse click events in the main loop when I click on an icon multiple times. That's ok, but I need only one. Only the first event. Here is minimal code that demonstrates the problem:
Code: Select all
win_nr = OpenWindow(#PB_Any, 0, 0, 400, 200, "test-window", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If win_nr = 0 : End : EndIf
hIcon = ExtractIcon_(0, "imageres.dll", 100)
AddSysTrayIcon(1, WindowID(win_nr), hIcon)
msgbox_title.s = "Attention !"
msgbox_body.s = "blah-blah-blah..."
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_SysTray
Select EventType()
Case #PB_EventType_LeftClick, #PB_EventType_LeftDoubleClick
Debug "LeftClick or LeftDoubleClick was detected on SysTray"
If FindWindow_(0, msgbox_title) = 0
MessageRequester(msgbox_title, msgbox_body, #MB_SYSTEMMODAL)
Else ; do nothing !
Debug "msgbox already opened"
EndIf
EndSelect
Case #PB_Event_CloseWindow
DestroyIcon_(hIcon)
Break
EndSelect
ForEver
Try clicking the taskbar icon several times and you will see a lot of repeated pop-up messages (one by one). Yes, I know that MessageRequester() function slows down the entire program until it is closed. but then why do the events accumulate if it's already open and the clicks continue ?
So...
How to clear the event queue from mouse clicks
Thank you in advance !
Re: Events in system tray
Posted: Wed Sep 04, 2024 12:13 pm
by Axolotl
Hi ZX80,
I am pretty sure that you can solve your problem by separating the events like this code below.
If I remember correctly than a Double Click always fires an Single Click as well, so in your code you react on all events....
Code: Select all
Procedure Trace(Message$)
Static s_index = 0
AddGadgetItem(0, s_index, RSet(Str(s_index), 4, "0") + ": " + Message$)
SetGadgetState(0, s_index)
s_index + 1
EndProcedure
win_nr = OpenWindow(#PB_Any, 0, 0, 400, 200, "test-window", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If win_nr = 0 : End : EndIf
ListViewGadget(0, 0, 0, 400, 200, $4000)
hIcon = ExtractIcon_(0, "imageres.dll", 100)
AddSysTrayIcon(1, WindowID(win_nr), hIcon)
msgbox_title.s = "Attention !"
msgbox_body.s = "blah-blah-blah..."
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_SysTray
Select EventType()
Case #PB_EventType_LeftClick
Trace("LeftClick on SysTray")
Case #PB_EventType_LeftDoubleClick
Trace("LeftDoubleClick on SysTray")
; Case #PB_EventType_LeftClick, #PB_EventType_LeftDoubleClick
; ; Debug "LeftClick or LeftDoubleClick was detected on SysTray"
; Trace("LeftClick or LeftDoubleClick was detected on SysTray")
; If FindWindow_(0, msgbox_title) = 0
; MessageRequester(msgbox_title, msgbox_body, #MB_SYSTEMMODAL)
; Else ; do nothing !
; ; Debug "msgbox already opened"
; Trace("msgbox already opened")
; EndIf
EndSelect
Case #PB_Event_CloseWindow
DestroyIcon_(hIcon)
Break
EndSelect
ForEver
Re: Events in system tray
Posted: Wed Sep 04, 2024 12:39 pm
by TI-994A
ZX80 wrote: Wed Sep 04, 2024 11:41 am...I'm getting a lot of mouse click events in the main loop when I click on an icon multiple times. That's ok, but I need only one.
The message requester is blocking the subsequent clicks from being processed, and those clicks are being processed only after the message requester is dismissed. If a message requester is required, perhaps implement a custom one, otherwise, other code logic should not block the clicks from being processed and cleared from the queue.
Here's an example:
Code: Select all
Global msgBoxWindow, msgBoxButton
Procedure msgBox(msg.s)
Shared win_nr
msgBoxWindow = OpenWindow(#PB_Any, 0, 0, 200, 100, "MsgBox",
#PB_Window_Tool | #PB_Window_WindowCentered,
WindowID(win_nr))
text = TextGadget(#PB_Any, 0, 20, 200, 30, msg, #PB_Text_Center)
msgBoxButton = ButtonGadget(#PB_Any, 50, 50, 100, 30, "OK")
EndProcedure
win_nr = OpenWindow(#PB_Any, 0, 0, 400, 200, "test-window", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If win_nr = 0 : End : EndIf
hIcon = ExtractIcon_(0, "imageres.dll", 100)
AddSysTrayIcon(1, WindowID(win_nr), hIcon)
msgbox_title.s = "Attention !"
msgbox_body.s = "blah-blah-blah..."
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_SysTray
Select EventType()
Case #PB_EventType_LeftClick, #PB_EventType_LeftDoubleClick
If Not systrayActivated
systrayActivated = #True
Debug "LeftClick or LeftDoubleClick was detected on SysTray"
msgBox("blah-blah-blah...")
EndIf
EndSelect
Case #PB_Event_Gadget
If EventGadget() = msgBoxButton
CloseWindow(msgBoxWindow)
systrayActivated = #False
EndIf
Case #PB_Event_CloseWindow
DestroyIcon_(hIcon)
Break
EndSelect
ForEver
Re: Events in system tray
Posted: Wed Sep 04, 2024 12:45 pm
by ZX80
Axolotl, good time ! Thanks for your answer.
I am pretty sure that you can solve your problem by separating the events like this code below.
I don't think that's the issue here. I think I've found a solution. Is this normal practice ?
Code: Select all
Global thread
Procedure PopupMsg(*x)
MessageRequester("Attention !", "blah-blah-blah...", #MB_SYSTEMMODAL)
thread = 0
EndProcedure
win_nr = OpenWindow(#PB_Any, 0, 0, 400, 200, "test-window", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If win_nr = 0 : End : EndIf
hIcon = ExtractIcon_(0, "imageres.dll", 100)
AddSysTrayIcon(1, WindowID(win_nr), hIcon)
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_SysTray
Select EventType()
Case #PB_EventType_LeftClick, #PB_EventType_LeftDoubleClick
Debug "LeftClick or LeftDoubleClick was detected on SysTray"
If thread = 0
thread = CreateThread(@PopupMsg(), 0)
Else
Debug "Close the previous Msgbox first."
EndIf
EndSelect
Case #PB_Event_CloseWindow
DestroyIcon_(hIcon)
Break
EndSelect
ForEver
By the way, the middle key is not processed on my system. In my case, it is combined with a wheel. Has anyone caught the events '
#PB_EventType_MouseEnter' and '
#PB_EventType_MouseLeave' in the system tray ?
I was looking
at this old thread.
Re: Events in system tray
Posted: Wed Sep 04, 2024 12:52 pm
by ZX80
Hello, TI-994A.
Thanks for the clarification. Your code works too.
Re: Events in system tray
Posted: Wed Sep 04, 2024 11:49 pm
by RASHAD
Hi ZX80
You may need non blocking message
Code: Select all
Prototype SplashMessageSetup(hWnd,lpText$,lpCaption$,uType,wLanguageID.w,dwMilliseconds)
Procedure SplashMessage(title$,text$,ms=1000,icon=#MB_ICONINFORMATION)
lib=OpenLibrary(#PB_Any,"user32.dll")
If lib
SplashMessageSetup.SplashMessageSetup=GetFunction(lib,"MessageBoxTimeoutW")
SplashMessageSetup(GetForegroundWindow_(),text$,title$,#MB_SETFOREGROUND|#MB_TOPMOST|#MB_TASKMODAL|icon,0,ms)
CloseLibrary(lib)
EndIf
EndProcedure
win_nr = OpenWindow(#PB_Any, 0, 0, 400, 200, "test-window", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If win_nr = 0 : End : EndIf
hIcon = ExtractIcon_(0, "imageres.dll", 100)
AddSysTrayIcon(1, WindowID(win_nr), hIcon)
msgbox_title.s = "Attention !"
msgbox_body.s = "blah-blah-blah..."
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_SysTray
Select EventType()
Case #PB_EventType_LeftClick, #PB_EventType_LeftDoubleClick
Debug "LeftClick or LeftDoubleClick was detected on SysTray"
If FindWindow_(0, msgbox_title) = 0
SplashMessage(msgbox_title,msgbox_body,1000)
Else ; do nothing !
Debug "msgbox already opened"
EndIf
EndSelect
Case #PB_Event_CloseWindow
DestroyIcon_(hIcon)
Break
EndSelect
ForEver
Re: Events in system tray
Posted: Thu Sep 05, 2024 7:24 am
by mk-soft
Works only under Windows with Thread, but not allways
Re: Events in system tray
Posted: Thu Sep 05, 2024 8:57 am
by ZX80
RASHAD, mk-soft, thank you for your attention to my question.
RASHAD, yes, I know about the SplashMessage. You already published this, if my memory serves me correctly. Thanks for this. But in this case it is not entirely appropriate here. In addition, this does not prevent multiple messages from appearing, since there is a timeout and the message is automatically closed. One follows another. I understand that this sounds stupid, and it's unlikely that anyone will click on the icon many times, but this should also be provided, right ? I don’t know if you’ve heard of such a term as “foolproofing” ? This is it. I was surprised that MessageRequester() in this case turned out to be non-blocking at all. And here I want to carefully ask: Is this a bug or not ?
Thank you all again !
Re: Events in system tray
Posted: Thu Sep 05, 2024 9:13 am
by ZX80
@
TI-994A
TI-994A wrote: Wed Sep 04, 2024 12:39 pm
The message requester is blocking the subsequent clicks from being processed, and those clicks are being processed only after the message requester is dismissed...
I'm very sorry, but why in my second code these clicks are not processed when the message is closed ? After all, in your opinion, they should accumulate somewhere in the message queue, right ? How is it that it magically clears itself ? In my second code we still see the response to clicks. You can see this in the debug window. I don't understand anything.

Re: Events in system tray
Posted: Thu Sep 05, 2024 10:59 am
by TI-994A
ZX80 wrote: Thu Sep 05, 2024 9:13 am... in my second code these clicks are not processed when the message is closed ? After all, in your opinion, they should accumulate somewhere in the message queue, right ? How is it that it magically clears itself ?
Hello again, @ZX80. The clicks are queued in your first example, because the conventional message requester blocks all event processing until it is closed. But now, in your second example,
the message requester is being called from a thread, so it no longer blocks the processing of subsequent clicks, and they are all processed instantly, one after another, thereby clearing the queue. Nothing blocked or queued.
I've commented your second example to explain this. My apologies, but I'm just trying to be clear, and in no way am I trying to be condescending with the simplistic explanations.
Code: Select all
Global thread
Procedure PopupMsg(*x)
MessageRequester("Attention !", "blah-blah-blah...", #MB_SYSTEMMODAL)
thread = 0
EndProcedure
win_nr = OpenWindow(#PB_Any, 0, 0, 400, 200, "test-window", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If win_nr = 0 : End : EndIf
hIcon = ExtractIcon_(0, "imageres.dll", 100)
AddSysTrayIcon(1, WindowID(win_nr), hIcon)
Repeat
Event = WaitWindowEvent()
Select Event
; example: left-click or left-double-click sysTray item 10 TIMES
; 1. all 10 sysTray click events will trigger this CASE
Case #PB_Event_SysTray
; 2. check each sysTray event type
Select EventType()
; 3. all 10 systTray event types are either left-click or
; left-double-click, so they will all trigger this CASE
Case #PB_EventType_LeftClick, #PB_EventType_LeftDoubleClick
; 4. all 10 left-click or left-double-click events
; will reach HERE and print this debug statement
Debug "LeftClick or LeftDoubleClick was detected on SysTray"
; 5. all 10 left-click or left-double-click events
; will also reach HERE...
; 6. but only the FIRST left-click or left-double-click
; event will satisfy the condition [If thread = 0]
If thread = 0
; 7. the FIRST left-click or left-double-click event
; enters this block and creates the msgBox thread
thread = CreateThread(@PopupMsg(), 0)
; 8. now the thread has been created so [thread != 0] anymore
; so the other 9 left-click or left-double-click events
; cannot enter this IF block and gets thrown to the ELSE block
Else
; 9. all the other 9 left-click or left-double-click events
; reach HERE instead and print this debug statement
Debug "Close the previous Msgbox first."
EndIf
; 10. all 10 systTray events have now been processed and cleared from the queue!
; when the thread terminates and [thread = 0] again the thread block can be
; reached and a new msgBox thread can be created again by subsequent events.
EndSelect
Case #PB_Event_CloseWindow
DestroyIcon_(hIcon)
Break
EndSelect
ForEver
Re: Events in system tray
Posted: Thu Sep 05, 2024 2:11 pm
by ZX80
TI-994A, thanks a lot !
Yes, everything is much clearer now. Sorry for not being attentive enough.
You're absolutely right about the thread. Thanks for your detailed comments.