?? lion-tutorial23.htm
字號:
<html>
<head>
<link rel="stylesheet" href="../../asm.css">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>
<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<p align="center">Tutorial 23: Tray Icon</p>
<hr size="1">
In this tutorial, we will learn how to put icons into system tray and how to create/use
a popup menu. <br>
Download the example <a href="files/tut23.zip">here</a>.
<h3> Theory:</h3>
System tray is the rectangular region in the taskbar where several icons reside.
Normally, you'll see at least a digital clock in it. You can also put icons in
the system tray too. Below are the steps you have to perform to put an icon into
the system tray:
<ol>
<li> Fill a NOTIFYICONDATA structure which has the following members:</li>
<ul>
<li> cbSize The size of this structure.</li>
<li> hwnd Handle of the window that will receive
notification when a mouse event occurs over the tray icon.</li>
<li> uID A constant that is
used as the icon's identifier. You are the one who decides on this value.
In case you have more than one tray icons, you will be able to check from
what tray icon the mouse notification is from.</li>
<li> uFlags Specify which members of this structure are
valid</li>
<ul>
<li> <b>NIF_ICON</b> The hIcon member is valid.</li>
<li> <b>NIF_MESSAGE</b> The uCallbackMessage member is valid.</li>
<li> <b>NIF_TIP</b> The szTip member is valid.</li>
</ul>
<li> uCallbackMessage The custom message that Windows will send to the
window specified by the hwnd member when mouse events occur over the tray
icon. You create this message yourself.</li>
<li> hIcon The handle of the icon you want to
put into the system tray</li>
<li> szTip A 64-byte array that contains
the string that will be used as the tooltip text when the mouse hovers over
the tray icon.</li>
</ul>
<li> Call Shell_NotifyIcon which is defined in shell32.inc. This function has
the following prototype:</li>
<p><br>
<b> Shell_NotifyIcon
PROTO dwMessage:DWORD ,pnid:DWORD</b>
<p> dwMessage is the type of message to send to the
shell. <br>
<b>NIM_ADD</b>
Adds an icon to the status area. <br>
<b>NIM_DELETE</b> Deletes
an icon from the status area. <br>
<b>NIM_MODIFY</b> Modifies
an icon in the status area. <br>
pnid is the pointer to a NOTIFYICONDATA structure
filled with proper values <br>
If you want to add an icon to the tray, use NIM_ADD message, if you want to
remove the icon, use NIM_DELETE.
</ol>
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):
<ul>
<li> wParam contains the ID of the icon. This is the same value you put into
uID member of NOTIFYICONDATA structure.</li>
<li> lParam The low word contains the mouse message. For example, if the
user right-clicked at the icon, lParam will contain WM_RBUTTONDOWN.</li>
</ul>
Most tray icon, however, displays a popup menu when the user right-click on it.
We can implement this feature by creating a popup menu and then call TrackPopupMenu
to display it. The steps are described below:
<ol>
<li> Create a popup menu by calling CreatePopupMenu. This function creates an
empty menu. It returns the menu handle in eax if successful.</li>
<li> Add menu items to it with AppendMenu, InsertMenu or InsertMenuItem.</li>
<li> 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.</li>
</ol>
Note: Beware of two annoying behaviors when you use a popup menu with a tray icon:
<ol>
<li> 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.</li>
<li> 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!</li>
</ol>
<h3> Example:</h3>
<b>.386</b> <br>
<b>.model flat,stdcall</b> <br>
<b>option casemap:none</b> <br>
<b>include \masm32\include\windows.inc</b> <br>
<b>include \masm32\include\user32.inc</b> <br>
<b>include \masm32\include\kernel32.inc</b> <br>
<b>include \masm32\include\shell32.inc</b> <br>
<b>includelib \masm32\lib\user32.lib</b> <br>
<b>includelib \masm32\lib\kernel32.lib</b> <br>
<b>includelib \masm32\lib\shell32.lib</b>
<p><b>WM_SHELLNOTIFY equ WM_USER+5</b> <br>
<b>IDI_TRAY equ 0</b> <br>
<b>IDM_RESTORE equ 1000</b> <br>
<b>IDM_EXIT equ 1010</b> <br>
<b>WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD</b>
<p><b>.data</b> <br>
<b>ClassName db "TrayIconWinClass",0</b> <br>
<b>AppName db "TrayIcon Demo",0</b> <br>
<b>RestoreString db "&Restore",0</b> <br>
<b>ExitString db "E&xit Program",0</b>
<p><b>.data?</b> <br>
<b>hInstance dd ?</b> <br>
<b>note NOTIFYICONDATA <></b> <br>
<b>hPopupMenu dd ?</b>
<p><b>.code</b> <br>
<b>start:</b> <br>
<b> invoke GetModuleHandle, NULL</b> <br>
<b> mov hInstance,eax</b> <br>
<b> invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT</b>
<br>
<b> invoke ExitProcess,eax</b>
<p><b>WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD</b>
<br>
<b> LOCAL wc:WNDCLASSEX</b> <br>
<b> LOCAL msg:MSG</b> <br>
<b> LOCAL hwnd:HWND</b> <br>
<b> mov wc.cbSize,SIZEOF WNDCLASSEX</b> <br>
<b> mov wc.style, CS_HREDRAW or CS_VREDRAW or
CS_DBLCLKS</b> <br>
<b> mov wc.lpfnWndProc, OFFSET WndProc</b> <br>
<b> mov wc.cbClsExtra,NULL</b> <br>
<b> mov wc.cbWndExtra,NULL</b> <br>
<b> push hInst</b> <br>
<b> pop wc.hInstance</b> <br>
<b> mov wc.hbrBackground,COLOR_APPWORKSPACE</b>
<br>
<b> mov wc.lpszMenuName,NULL</b> <br>
<b> mov wc.lpszClassName,OFFSET ClassName</b>
<br>
<b> invoke LoadIcon,NULL,IDI_APPLICATION</b> <br>
<b> mov wc.hIcon,eax</b> <br>
<b> mov wc.hIconSm,eax</b> <br>
<b> invoke LoadCursor,NULL,IDC_ARROW</b> <br>
<b> mov wc.hCursor,eax</b> <br>
<b> invoke RegisterClassEx, addr wc</b> <br>
<b> invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR
AppName,\</b> <br>
<b>WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,\</b>
<br>
<b> CW_USEDEFAULT,350,200,NULL,NULL,\</b>
<br>
<b> hInst,NULL</b>
<br>
<b> mov hwnd,eax</b> <br>
<b> .while TRUE</b> <br>
<b> invoke GetMessage, ADDR msg,NULL,0,0</b>
<br>
<b> .BREAK .IF (!eax)</b> <br>
<b> invoke TranslateMessage, ADDR
msg</b> <br>
<b> invoke DispatchMessage, ADDR msg</b>
<br>
<b> .endw</b> <br>
<b> mov eax,msg.wParam</b> <br>
<b> ret</b> <br>
<b>WinMain endp</b>
<p><b>WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM</b> <br>
<b> LOCAL pt:POINT</b> <br>
<b> .if uMsg==WM_CREATE</b> <br>
<b> invoke CreatePopupMenu</b> <br>
<b> mov hPopupMenu,eax</b> <br>
<b> invoke AppendMenu,hPopupMenu,MF_STRING,IDM_RESTORE,addr
RestoreString</b> <br>
<b> invoke AppendMenu,hPopupMenu,MF_STRING,IDM_EXIT,addr
ExitString</b> <br>
<b> .elseif uMsg==WM_DESTROY</b> <br>
<b> invoke DestroyMenu,hPopupMenu</b>
<br>
<b> invoke PostQuitMessage,NULL</b>
<br>
<b> .elseif uMsg==WM_SIZE</b> <br>
<b> .if wParam==SIZE_MINIMIZED</b>
<br>
<b> mov note.cbSize,sizeof
NOTIFYICONDATA</b> <br>
<b> push hWnd</b>
<br>
<b> pop note.hwnd</b>
<br>
<b> mov note.uID,IDI_TRAY</b>
<br>
<b> mov note.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP</b>
<br>
<b> mov note.uCallbackMessage,WM_SHELLNOTIFY</b>
<br>
<b> invoke
LoadIcon,NULL,IDI_WINLOGO</b> <br>
<b> mov note.hIcon,eax</b>
<br>
<b> invoke
lstrcpy,addr note.szTip,addr AppName</b> <br>
<b> invoke
ShowWindow,hWnd,SW_HIDE</b> <br>
<b> invoke
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -