if you want to add an icon to the tray, use nim_add message, if you want to remove the icon, use nim_delete.
that's all there is to it. but most of the time, you're not content in just putting an icon there. you need to be able to respond to the mouse events over the tray icon. you can do this by processing the message you specified in ucallbackmessage member of notifyicondata structure. this message has the following values in wparam and lparam (special thanks to s__d for the info):- wparam contains the id of the icon. this is the same value you put into uid member of notifyicondata structure.
- lparam the low word contains the mouse message. for example, if the user right-clicked at the icon, lparam will contain wm_rbuttondown.
- create a popup menu by calling createpopupmenu. this function creates an empty menu. it returns the menu handle in eax if successful.
- add menu items to it with appendmenu, insertmenu or insertmenuitem.
- when you want to display the popup menu where the mouse cursor is, call getcursorpos to obtain the screen coordinate of the cursor and then call trackpopupmenu to display the menu. when the user selects a menu item from the popup menu, windows sends wm_command message to your window procedure just like normal menu selection.
- when the popup menu is displayed, if you click anywhere outside the menu, the popup menu will not disappear immediately as it should be. this behavior occurs because the window that will receive the notifications from the popup menu must be the foreground window. just call setforegroundwindow will correct it.
- after calling setforegroundwindow, you will find that the first time the popup menu is displayed, it works ok but on the subsequent times, the popup menu will show up and close immediately. this behavior is "intentional", to quote from msdn. the task switch to the program that is the owner of the tray icon in the near future is necessary. you can force this task switch by posting any message to the window of the program. just use postmessage, not sendmessage!
example:
.386.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\shell32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\shell32.lib
wm_shellnotify equ wm_user+5
idi_tray equ 0
idm_restore equ 1000
idm_exit equ 1010
winmain proto :dword,:dword,:dword,:dword
.data
classname db "trayiconwinclass",0
appname db "trayicon demo",0
restorestring db "&restore",0
exitstring db "e&xit program",0
.data?
hinstance dd ?
note notifyicondata <>
hpopupmenu dd ?
.code
start:
invoke getmodulehandle, null
mov hinstance,eax
invoke winmain, hinstance,null,null, sw_showdefault
invoke exitprocess,eax
winmain proc hinst:hinstance,hprevinst:hinstance,cmdline:lpstr,cmdshow:dword
local wc:wndclassex
local msg:msg
local hwnd:hwnd
mov wc.cbsize,sizeof wndclassex
mov wc.style, cs_hredraw or cs_vredraw or cs_dblclks
mov wc.lpfnwndproc, offset wndproc
mov wc.cbclsextra,null
mov wc.cbwndextra,null
push hinst
pop wc.hinstance
mov wc.hbrbackground,color_appworkspace
mov wc.lpszmenuname,null
mov wc.lpszclassname,offset classname
invoke loadicon,null,idi_application
mov wc.hicon,eax
mov wc.hiconsm,eax
invoke loadcursor,null,idc_arrow
mov wc.hcursor,eax
invoke registerclassex, addr wc