Page 1 of 2
Proper notifications from a SystrayIcon balloon message
Posted: Fri Feb 03, 2012 3:20 pm
by merendo
Cheers!
I've put together some code, which displays a Balloon message for a given SystrayIcon. Now I know this Balloon message can hand me back some user events, which I'd like to process, but I'm too clumsy with Window callbacks, so I'd appreciate some help here.
The
MSDN documentation for NOTIFYICONDATA does say something about the events being parsed through the lParam, but it doesn't say which values I should look for when I want to know, for example, when the user has clicked the X on the Balloon message.
EDIT: I just learned that I wanna look for the event values #NIN_BALLOONTIMEOUT, #NIN_BALLOONHIDE and #NIN_BALLOONUSERCLICK, but I still don't know how or where to receive them.
Code: Select all
Structure MY_NOTIFYICONDATA
cbSize.l
hWnd.i
uID.l
uFlags.l
uCallbackMessage.l
hIcon.i
szTip.s{128}
dwState.l
dwStateMark.l
szInfo.s{256}
StructureUnion
uTimeout.l
uVersion.l
EndStructureUnion
szInfoTitle.s{64}
dwInfoFlags.l
EndStructure
Procedure MyCallback(WindowID, Message, wParam, lParam)
If WindowID = WindowID(0)
; I assume I wanna process the event the system sends me here.
EndIf
EndProcedure
OpenWindow(0, 0, 0, 200, 40, "Icontest", #PB_Window_SystemMenu)
ButtonGadget(0, 5, 5, 190, 30, "Show balloon message")
; You might wanna specify a path which corresponds to any valid .ico file on your system.
LoadImage(0, "C:\Programme\PureBasic\Examples\Sources - Advanced\Waponez II\Waponez.ico")
AddSysTrayIcon(0, WindowID(0), ImageID(0))
SysTrayIconToolTip(0, "Naah, I ain't no systray icon, I'm just cleanin' down 'ere.")
;SetWindowCallback(@MyCallback(), 0) ; Uncomment me and - voilá - the button disappears. WTF?
NIData.MY_NOTIFYICONDATA
NIData\cbSize = SizeOf(MY_NOTIFYICONDATA)
NIData\hWnd = WindowID(0)
NIData\uFlags = #NIF_INFO
NIData\szInfo = "I'm just a small speech bubble."
NIData\uTimeout = 15000
NIData\uVersion = #NOTIFYICON_VERSION
NIData\szInfoTitle = "Hey there!"
NIData\dwInfoFlags = #NIIF_INFO
Repeat
event = WaitWindowEvent()
If event = #PB_Event_Gadget
If EventGadget() = 0
Shell_NotifyIcon_(#NIM_MODIFY, NIData)
EndIf
EndIf
Until event = #PB_Event_CloseWindow
Weird enough, once I assign my window the callback procedure (incomplete), the button disappears. Anyone got an idea why that is?
Help appreciated!
merendo
Re: Proper notifications from a SystrayIcon balloon message
Posted: Fri Feb 03, 2012 5:49 pm
by merendo
Persistence leads to victory, isn't that right? I worked out most issues, here's my updated code:
Code: Select all
Structure MY_NOTIFYICONDATA
cbSize.l
hWnd.i
uID.l
uFlags.l
uCallbackMessage.l
hIcon.i
szTip.s{128}
dwState.l
dwStateMark.l
szInfo.s{256}
StructureUnion
uTimeout.l
uVersion.l
EndStructureUnion
szInfoTitle.s{64}
dwInfoFlags.l
EndStructure
#WINDOW = 0
Enumeration
#BUTTON_SHOW
#BUTTON_HIDE
#SYSTRAYICON
EndEnumeration
Procedure MyCallback(WindowID, Message, wParam, lParam)
If WindowID = WindowID(0)
If Message = 99999 ; Does that make sense?
If wParam = #SYSTRAYICON
Select lParam
Case #NIN_BALLOONTIMEOUT
Debug "Balloon timed out or was closed by the user"
Case #NIN_BALLOONUSERCLICK
Debug "Balloon got clicked by the user"
Case #NIN_BALLOONHIDE
Debug "Balloon got hidden"
EndSelect
EndIf
EndIf
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(#WINDOW, 0, 0, 200, 75, "Icontest", #PB_Window_SystemMenu)
ButtonGadget(#BUTTON_SHOW, 5, 5, 190, 30, "Show balloon message")
ButtonGadget(#BUTTON_HIDE, 5, 40, 190, 30, "Hide balloon message")
; You might wanna specify a path which corresponds to any valid .ico file on your system.
LoadImage(0, "C:\Programme\PureBasic\Examples\Sources - Advanced\Waponez II\Waponez.ico")
AddSysTrayIcon(#SYSTRAYICON, WindowID(0), ImageID(0))
SysTrayIconToolTip(#SYSTRAYICON, "Naah, I ain't no systray icon, I'm just cleanin' down 'ere.")
SetWindowCallback(@MyCallback(), 0)
NIData.MY_NOTIFYICONDATA
NIData\cbSize = SizeOf(MY_NOTIFYICONDATA)
NIData\hWnd = WindowID(0)
NIData\uID = #SYSTRAYICON
NIData\uFlags = #NIF_INFO | #NIF_MESSAGE
NIData\uCallbackMessage = 99999
NIData\uTimeout = 10
NIData\uVersion = #NOTIFYICON_VERSION
NIData\szInfoTitle = "Hey there!"
NIData\dwInfoFlags = #NIIF_INFO
Repeat
event = WaitWindowEvent()
If event = #PB_Event_Gadget
Select EventGadget()
Case #BUTTON_SHOW:
NIData\szInfo = "I'm just a small speech bubble."
Shell_NotifyIcon_(#NIM_MODIFY, NIData)
Case #BUTTON_HIDE:
NIData\szInfo = ""
Shell_NotifyIcon_(#NIM_MODIFY, NIData)
EndSelect
EndIf
Until event = #PB_Event_CloseWindow
I'm still not sure about which NOTIFYICONDATA\uCallbackMessage code to use, though. I used 99999 here because I figured that is likely to be available. According to MSDN, message is "An application-defined message identifier. The system uses this identifier to send notification messages to the window identified in hWnd." Can I just freely use any number I want here??
Re: Proper notifications from a SystrayIcon balloon message
Posted: Fri Feb 03, 2012 6:55 pm
by c4s
Nice code, looks useful to me!
I'd really say you can define any id you want to as the quoted description of MSDN says so.
And a small tip. Use #PB_Compiler_Home for the icon path, like this:
Code: Select all
LoadImage(0, #PB_Compiler_Home + "\Examples\Sources - Advanced\Waponez II\Waponez.ico")
Re: Proper notifications from a SystrayIcon balloon message
Posted: Sat Feb 04, 2012 10:44 am
by merendo
Well, I'm not sure now. When I add the line 'debug Message' in the Callback procedure (inside the If hWnd = WindowID() block), I get all sorts of messages whenever I interact with the window (like hovering over the window with the mouse), so it seems there are at least a good handfull of reserved codes.
Perhaps there is one, which I can safely use or even one which is meant for exactly this purpose? All you Callback geeks, where are you?

Re: Proper notifications from a SystrayIcon balloon message
Posted: Sat Feb 04, 2012 11:45 am
by Kwai chang caine
Works great on XP
Thanks for sharing
Re: Proper notifications from a SystrayIcon balloon message
Posted: Tue Feb 07, 2012 2:38 pm
by merendo
You're very welcome. However, my original questions still remains unanswered: Which callbackMessage can I safely use without running the risk of interfering with existing codes? 99999 probably works, but this number is completely random and a shot in the dark - not a satisfactory solution to me.
Re: Proper notifications from a SystrayIcon balloon message
Posted: Tue Feb 07, 2012 5:54 pm
by c4s
I'd say using
#WM_APP+1 is save.
Re: Proper notifications from a SystrayIcon balloon message
Posted: Tue Feb 07, 2012 6:03 pm
by merendo
Great. I know who to come back to if it doesn't work
Thank you!
Btw: I got carried away and converted my example into a complete app.
http://www.mediafire.com/?v9x45sjg4e1gz10 (Yeah, I know there is a better way to capture those Icons, but at the time I wrote this, I didn't care.)
Re: Proper notifications from a SystrayIcon balloon message
Posted: Mon Feb 20, 2012 5:51 pm
by merendo
Okay, problem. Please run this code:
Code: Select all
Structure MY_NOTIFYICONDATA
cbSize.l
hWnd.i
uID.l
uFlags.l
uCallbackMessage.l
hIcon.i
szTip.s{128}
dwState.l
dwStateMark.l
szInfo.s{256}
StructureUnion
uTimeout.l
uVersion.l
EndStructureUnion
szInfoTitle.s{64}
dwInfoFlags.l
EndStructure
#WINDOW = 0
Enumeration
#BUTTON_SHOW
#BUTTON_HIDE
#SYSTRAYICON
EndEnumeration
Procedure MyCallback(WindowID, Message, wParam, lParam)
If WindowID = WindowID(0)
If Message = 99999 ; Does that make sense?
If wParam = #SYSTRAYICON
Select lParam
Case #NIN_BALLOONTIMEOUT
Debug "Balloon timed out or was closed by the user"
Case #NIN_BALLOONUSERCLICK
Debug "Balloon got clicked by the user"
Case #NIN_BALLOONHIDE
Debug "Balloon got hidden"
EndSelect
EndIf
EndIf
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(#WINDOW, 0, 0, 200, 75, "Icontest", #PB_Window_SystemMenu)
ButtonGadget(#BUTTON_SHOW, 5, 5, 190, 30, "Show balloon message")
ButtonGadget(#BUTTON_HIDE, 5, 40, 190, 30, "Hide balloon message")
; You might wanna specify a path which corresponds to any valid .ico file on your system.
LoadImage(0, #PB_Compiler_Home + "\Examples\Sources - Advanced\Waponez II\Waponez.ico")
AddSysTrayIcon(#SYSTRAYICON, WindowID(0), ImageID(0))
SysTrayIconToolTip(#SYSTRAYICON, "Naah, I ain't no systray icon, I'm just cleanin' down 'ere.")
SetWindowCallback(@MyCallback(), 0)
NIData.MY_NOTIFYICONDATA
NIData\cbSize = SizeOf(MY_NOTIFYICONDATA)
NIData\hWnd = WindowID(0)
NIData\uID = #SYSTRAYICON
NIData\uFlags = #NIF_INFO | #NIF_MESSAGE
NIData\uCallbackMessage = 99999
NIData\uTimeout = 10
NIData\uVersion = #NOTIFYICON_VERSION
NIData\szInfoTitle = "Hey there!"
NIData\dwInfoFlags = #NIIF_INFO
Repeat
event = WaitWindowEvent()
If event = #PB_Event_Gadget
Select EventGadget()
Case #BUTTON_SHOW:
NIData\szInfo = "I'm just a small speech bubble."
Shell_NotifyIcon_(#NIM_MODIFY, NIData)
Case #BUTTON_HIDE:
NIData\szInfo = ""
Shell_NotifyIcon_(#NIM_MODIFY, NIData)
EndSelect
EndIf
If event = #PB_Event_SysTray
If EventGadget() = #SYSTRAYICON
MessageRequester("Message", "Systrayicon got clicked.")
EndIf
EndIf
Until event = #PB_Event_CloseWindow
First, try clicking on the systrayicon
before first displaying a balloon message (the messagerequester should appear), then display a balloon message, then try clicking the systrayicon again (no messagerequester should appear). I have worked out that whenever I set the #NIF_MESSAGE flag in NIData\uFlags (meaning that the NIData\uCallbackMessage is valid), the PureBasic event handler somehow won't receive events from that systrayicon anymore. Does anybody know how to restore proper handling of these events?
Re: Proper notifications from a SystrayIcon balloon message
Posted: Mon Feb 20, 2012 7:06 pm
by RASHAD
Change
Code: Select all
NIData.MY_NOTIFYICONDATA
NIData\cbSize = SizeOf(MY_NOTIFYICONDATA)
NIData\hWnd = WindowID(0)
NIData\uID = #SYSTRAYICON
NIData\uFlags = #NIF_INFO
NIData\uCallbackMessage = 99999
NIData\uTimeout = 10
NIData\uVersion = #NOTIFYICON_VERSION
NIData\szInfoTitle = "Hey there!"
NIData\dwInfoFlags = #NIIF_INFO
Re: Proper notifications from a SystrayIcon balloon message
Posted: Mon Feb 20, 2012 7:19 pm
by merendo
If I do that (i.e. remove the #NIF_MESSAGE flag from NIData\uFlags), the events for the info bubble don't get processed anymore...
Re: Proper notifications from a SystrayIcon balloon message
Posted: Mon Feb 20, 2012 9:13 pm
by RASHAD
After using Shell_NotifyIcon_() the PB #PB_Event_SysTray change permanent
Next is a workaround for time being till we find another way
Code: Select all
Structure MY_NOTIFYICONDATA
cbSize.l
hWnd.i
uID.l
uFlags.l
uCallbackMessage.l
hIcon.i
szTip.s{128}
dwState.l
dwStateMark.l
szInfo.s{256}
StructureUnion
uTimeout.l
uVersion.l
EndStructureUnion
szInfoTitle.s{64}
dwInfoFlags.l
EndStructure
#WINDOW = 0
Enumeration
#BUTTON_SHOW
#BUTTON_HIDE
#SYSTRAYICON
EndEnumeration
Procedure MyCallback(WindowID, Message, wParam, lParam)
If WindowID = WindowID(0)
If Message = #WM_NOTIFYICON ; Does that make sense?
If wParam = #SYSTRAYICON
Select lParam
Case #NIN_BALLOONTIMEOUT
Debug "Balloon timed out or was closed by the user"
AddSysTrayIcon(#SYSTRAYICON, WindowID(0), ImageID(0))
Case #NIN_BALLOONUSERCLICK
Debug "Balloon got clicked by the user"
AddSysTrayIcon(#SYSTRAYICON, WindowID(0), ImageID(0))
Case #NIN_BALLOONHIDE
Debug "Balloon got hidden"
AddSysTrayIcon(#SYSTRAYICON, WindowID(0), ImageID(0))
EndSelect
EndIf
EndIf
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(#WINDOW, 0, 0, 200, 75, "Icontest", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ButtonGadget(#BUTTON_SHOW, 5, 5, 190, 30, "Show balloon message")
ButtonGadget(#BUTTON_HIDE, 5, 40, 190, 30, "Hide balloon message")
; You might wanna specify a path which corresponds to any valid .ico file on your system.
LoadImage(0, #PB_Compiler_Home + "\Examples\Sources - Advanced\Waponez II\Waponez.ico")
AddSysTrayIcon(#SYSTRAYICON, WindowID(0), ImageID(0))
SysTrayIconToolTip(#SYSTRAYICON, "Naah, I ain't no systray icon, I'm just cleanin' down 'ere.")
SetWindowCallback(@MyCallback(), 0)
NIData.MY_NOTIFYICONDATA
NIData\cbSize = SizeOf(MY_NOTIFYICONDATA)
NIData\hWnd = WindowID(0)
NIData\uID = #SYSTRAYICON
NIData\uFlags = #NIF_INFO | #NIF_MESSAGE
NIData\uCallbackMessage = #WM_NOTIFYICON
NIData\uTimeout = 2
NIData\uVersion = #NOTIFYICON_VERSION
NIData\szInfoTitle = "Hey there!"
NIData\dwInfoFlags = #NIIF_INFO
Repeat
event = WaitWindowEvent()
If event = #PB_Event_Gadget
Select EventGadget()
Case #BUTTON_SHOW:
NIData\szInfo = "I'm just a small speech bubble."
Shell_NotifyIcon_(#NIM_MODIFY, NIData)
Case #BUTTON_HIDE:
NIData\szInfo = ""
Shell_NotifyIcon_(#NIM_MODIFY, NIData)
EndSelect
EndIf
If event = #PB_Event_SysTray
If EventGadget() = #SYSTRAYICON
MessageRequester("Message", "Systrayicon got clicked.")
EndIf
EndIf
Until event = #PB_Event_CloseWindow
Re: Proper notifications from a SystrayIcon balloon message
Posted: Mon Feb 20, 2012 9:21 pm
by merendo
Seems to work fine for me now. Thank you very much!
Re: Proper notifications from a SystrayIcon balloon message
Posted: Mon Feb 20, 2012 10:56 pm
by RASHAD
Hi merendo
I did not like the previous workaround
Change
Code: Select all
Procedure MyCallback(WindowID, Message, wParam, lParam)
If WindowID = WindowID(0)
If Message = #WM_NOTIFYICON ; Does that make sense?
If wParam = #SYSTRAYICON
Select lParam
Case #NIN_BALLOONTIMEOUT
Debug "Balloon timed out or was closed by the user"
Case #NIN_BALLOONUSERCLICK
Debug "Balloon got clicked by the user"
Case #NIN_BALLOONHIDE
Debug "Balloon got hidden"
Case #WM_LBUTTONUP
MessageRequester("Message", "Systrayicon got clicked.")
EndSelect
EndIf
EndIf
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Re: Proper notifications from a SystrayIcon balloon message
Posted: Tue Feb 21, 2012 7:38 am
by merendo
That works even better. Your efforts are much appreciated, thanks!
Perhaps when someone from the PB team reads this posting, they could tell us which uCallbackMessage the Notifyicon needs to be reassigned in order to restore the systray icon to it's original function, but until then, the workaround provides a satisfactory solution.