The shortcut icon in the twenty-third class system tray
In this lesson, we will learn how to put the small icon into the system tray and how to create and use pop-up menus.
Theory: The system tray refers to a square area in the task bar, and some small icons can be placed in this area, usually you can see the latest time available in the system. You can of course put the shortcut small icon here. Here's the steps:
Set the value of the member variable of the NOTIFYICONDATA type structure variable:
CBSIZE The size of the structure. Hwnd window handle. When the mouse slides over the small icon, the window will receive the relevant message. UID small icon ID number. You can take anything, just when your application has more than one small icon, you have to distinguish the message that the small icon receives the mouse, that is, the ID number must be unique. UFLAGS specifies those members variables of the structural variables.
NIF_ICON is valid. Nif_message is valid. NIF_TIP is valid. UcallbackMessage custom message. When the mouse is moving to the small icon, the Windows housing will send the message to your application. The value of this message You can define it yourself. Hicon is placed in the handle of the icon in the system tray. The SZTIP 64-byte buffer is used to place a prompt string that the string is displayed when the mouse is on a small icon. Call the shell_notifyicon function. This function is defined in shell32.inc, whose prototype is as follows: Shell_Notifyicon Proto DwMessage: DWORD, PNID: DWORD DWMESSAGE is a message sent to a Windows shell: NIM_ADD adds a small icon to the system tray area. NIM_DELETE Removes a small icon from the system tray. NIM_MODIFY Modify the small icon. PNID is a pointer to the NOTIFYICONDATA structure variable. Use the NIM_DELETE message when you want to join a small icon and use NIM_ADD and delete it. Basic news is these. But in most cases, you won't just satisfy a small icon. You must also make an appropriate response to mouse events. You can set the message you want to process in the member variable of the Notifyicondata structure variable, and the Windows House will notify you the application when these events occur. As the parameters of the messages, the values of WPARAM and LPARAM are as follows:
WPARAM small icon ID number. It is the same as the value set in the member variable UID in the NOTIFYICONDATA structure variable. LPARAM low words contain mouse messages. For example, when the user presses the right button on the small icon, the WM_RBUTTONDOWN message will be included in the LPARAM. Most small icons in the system tray, one menu pops up when the user is right-click to make it easy for users to choose. We can create a menu first, then call the TRACKPOPUPMENU function to display it. Proceed as follows:
Call the createPopUpMenu function to create a menu. This function creates an empty menu. If successful, the handle of the menu will be returned in EAX. Call the AppendMenu, InsertMenu or InsertMenuItem to join the menu item to the menu. When you want to display the menu at the current mouse location, call the getCursorPosition function to get the current screen location, then call TRACKPOPUPMENU to display the menu. When the user selects a menu item from the pop-up menu, Windows will send the WM_COMMAND message to your application's message processing, which is the same as the usual menu. Note: There are two more annoying things when you use small icons in the system tray:
This menu may not disappear immediately as usual. This is because the window from the pop-up receiving message must be the foreground window. Call the setForegroundWindow function to correct the error; after calling the SetForegroundWindow function, you will find that the first time the pop-up menu will pop up normally and work very well. But then, the menu is just disappeared immediately. It is intentional depending on MSDN. In order to keep the pop-up menu, you must require the next to switch to the main window of the program. You can force task to switch by mailing any message to the window. Note To use PostMessage instead of SendMessage. example:
.386
.Model flat, stdcall
Option CaseMAP: NONE
INCLUDE /MASM32/INCLUDE/Windows.inc
INCLUDE /MASM32/INCLUDE/USER32.INC
INCLUDE /MASM32/INCLUDE / WANEL32.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 invoke CreateWindowEx, WS_EX_CLIENTEDGE, aDDR ClassName, aDDR AppName, / WS_OVERLAPPED WS_CAPTION WS_SYSMENU WS_MINIMIZEBOX WS_MAXIMIZEBOX WS_VISIBLE, CW_USEDEFAULT , / CW_USEDEFAULT, 350, 200, NULL, NULL, / HINST, NULL MOV HWND, EAX .While True Invoke GetMessage, Addr MSG, NULL, 0, 0 .Break .if (! EAX) Invoke TranslateMessage, Addr Msg Invoke DispatchMessage, Addr Msg .Endw Mov Eax, Msg.wParam Ret Winmain Endp
WndProc proc hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM LOCAL pt: POINT .if uMsg == WM_CREATE invoke CreatePopupMenu mov hPopupMenu, eax invoke AppendMenu, hPopupMenu, MF_STRING, IDM_RESTORE, addr RestoreString invoke AppendMenu, hPopupMenu, MF_STRING , IDM_EXIT, addr ExitString .elseif uMsg == WM_DESTROY invoke DestroyMenu, hPopupMenu invoke PostQuitMessage, NULL .elseif uMsg == WM_SIZE .if wParam == SIZE_MINIMIZED mov note.cbSize, sizeof NOTIFYICONDATA push hWnd pop note.hwnd mov note.uID, IDI_TRAY mov note.uFlags, NIF_ICON NIF_MESSAGE NIF_TIP mov note.uCallbackMessage, WM_SHELLNOTIFY invoke LoadIcon, NULL, IDI_WINLOGO mov note.hIcon, eax invoke lstrcpy, addr note.szTip, addr AppName invoke ShowWindow, hWnd, SW_HIDE invoke Shell_NotifyIcon, NIM_ADD, addr Note .ndif .elseif uMSG == WM_COMMAND .if lParam == 0 invoke Shell_NotifyIcon, NIM_DELETE, addr note mov eax, wParam .if ax == IDM_RESTORE invoke ShowWindow, hWnd, SW_RESTORE .else invoke DestroyWindow, hWnd .endif .endif .elseif uMsg == WM_SHELLNOTIFY .if wParam == IDI_TRAY .if lParam == WM_RBUTTONDOWN invoke GetCursorPos, addr pt invoke SetForegroundWindow, hWnd invoke TrackPopupMenu, hPopupMenu, TPM_RIGHTALIGN, pt.x, pt.y, NULL, hWnd, NULL invoke PostMessage, hWnd, WM_NULL, 0,0 .elseif lParam = =
WM_LBUTTONDBLCLK INVOKE SendMessage, HWND, WM_COMMAND, IDM_RESTORE, 0.endif.ndif.else Invoke DefWindowProc, Hwnd, UMSG, WPARAM, LPARAM RET .Endif xor Eax, Eax Ret WndProc Endped Start
Analysis: This program will display a simple window. When you press the minimize button, the window will hide, and then put a small icon to the system tray. When you double-click the small icon, the application will restore yourself and remove the small icon from the system tray. When you right-click on a small icon, a pop-up menu is displayed. You can choose to recover the window or exit the application in the menu.
.if uMsg == WM_CREATE invoke CreatePopupMenu mov hPopupMenu, eax invoke AppendMenu, hPopupMenu, MF_STRING, IDM_RESTORE, addr RestoreString invoke AppendMenu, hPopupMenu, MF_STRING, IDM_EXIT, addr ExitString
When the main window is created, a pop-up menu will be created and join two menu items. The syntax of the appendmenu is as follows:
Appendmenu Proto Hmenu: DWORD, UFLAGS: DWORD, UidNewItem: DWORD, LPNEWITEM: DWORD
HMENU is the handle of the menu that will join the menu item. UFLAGS tells Windows The menu item to be added is a bitmap, a string, or a self-drawn project and is available, not available or gray display. You can get information about all flags from the Win32 API guide. In our example, use the flag bit mf_string, which means that the menu item we join is a string. UidNewItem is the ID number of the menu item. This is a user-defined value that is used to uniquely represent the menu item. . lpnewItem is used to specify the content of the menu item, and the specifically represents what depends on the flag specified in UFLAGS. We have specified the MF_String flag in front, so it represents a string
After the main window is created, the user can start testing. Press the minimization key at this time.
The WM_SIZE message will be received when a window is minimized, where the value in the WPARAM parameter is SIZE_MINIMIZED.
.elseif uMsg == WM_SIZE .if wParam == SIZE_MINIMIZED mov note.cbSize, sizeof NOTIFYICONDATA push hWnd pop note.hwnd mov note.uID, IDI_TRAY mov note.uFlags, NIF_ICON NIF_MESSAGE NIF_TIP mov note.uCallbackMessage, WM_SHELLNOTIFY invoke LoadIcon, NULL, IDI_WINLOGO mov note.hIcon, eax invoke lstrcpy, addr note.szTip, addr AppName invoke ShowWindow, hWnd, SW_HIDE invoke Shell_NotifyIcon, NIM_ADD, addr note .endif when we come to NOTIFYICONDATA type structure variable assignment. IDi_tray is a numerical constant defined at the beginning of the code, and you can set its value arbitrarily. Since we only have an icon, this is not important. If you want to join several system icons, then each icon has a unique ID number. Since we specified an icon Nif_icon, we have to specify all the flags in the UFLAGS member variable, and we also specify a custom message Nif_Message and help text NIF_TIP. WM_SHELLNOTIFY is defined as WM_USER 5, as long as it is the only value, it doesn't matter how much, as long as it is greater than WM_USER. We use the icon when Windows login, of course, you can use the icon you want to use, you can load from the resource from the resource using the loadICON function, which returns an icon handle. Finally we put in the SZTIP to the prompt display when the mouse is placed on the icon. In order to achieve "minimize the effect of only the icon", we hide the main window at this time. Next, we call the shell_notifyicon function and specify the flag bit NIM_ADD to add the icon to the system tray.
Now our main window is hidden, the icon is displayed in the system tray. If you let the mouse slipper from the icon, you will see the prompt text. If you double-click the small icon, the main window will display, the icon will disappear.
.elseif uMsg == WM_SHELLNOTIFY .if wParam == IDI_TRAY .if lParam == WM_RBUTTONDOWN invoke GetCursorPos, addr pt invoke SetForegroundWindow, hWnd invoke TrackPopupMenu, hPopupMenu, TPM_RIGHTALIGN, pt.x, pt.y, NULL, hWnd, NULL invoke PostMessage, HWnd, WM_NULL, 0, 0 .ELSEIF LPARAM == WM_LButtondblclk Invoke SendMessage, Hwnd, WM_COMMAND, IDM_RESTORE, 0.endif.ndif.
When a mouse event occurs in the icon in the system tray, your window will receive a WM_SHELLNOTIFY message, which is specified in the UCALLBACKMESSAGE member variable. When the message is received, the wPARAM contains the ID number of the icon, and the raw data of the mouse action is included in the LPARAM. In the above code, we first tested whether it is the message we are interested in. If so, let's see what news is. Because we only interested right-click and double-click event, we only process WM_RBUTTONDOWN and WM_LBUTTONDBLCLK messages. If it is WM_RBUTTONDOWN, we call getCursorPos to get the current screen location where the mouse cursor is located. Note that I refer to the screen position, that is, its coordinates are relative to the entire screen. For example, if the parsing of the screen reads 640 * 480, then the coordinates of its lower right corner are x == 639, y == 479. If you want to convert the screen position into a window coordinate, you can call the ScreenToClient function We want to display the pop-up menu in the current location, we call the TrackPopUpMenu function, which requires the coordinates of the screen, and the coordinates returned by the getCursorpos function. It is used to use it. The prototype of TRACKPOPUPMENU is as follows: TRACKPOPUPMENU PROTO HMENU: DWORD, UFLAGS: DWORD, X: DWORD, Y: DWORD, NRESERVED: DWORD, HWND: DWORD, PRCRECT: DWORD
HMENU is a handle of pop-up menu. Selection of UFLAGS features. Where to place (relative to the coordinate specified) menu, the mouse button is used to track the pop-up menu. In our example, we use the TPM_RightAlign flag to specify the pop-up menu on the left side of the coordinates. X and Y specify the screen coordinates of the menu. NRESERVED must be NULL. HWnd is the handle of the window to receive the message. PrcRect Specifies a rectangular area. If you press the mouse outside of the rectangular area, the menu will disappear. Generally we set this value to null, so when the user presses the mouse outside the menu, the menu disappears immediately.
When the user doubles the icon, we send our own window to the WM_COMMAND message and specify the message as IDM_RESTORE, which can achieve the same effect as the "RESTORE" menu item in the pop-up menu. In order to be able to receive a double-click message, the main window must have a CS_DBLCLKS style.
Invoke shell_notifyicon, nim_delete, addr note max
When the user selects the restore the main window, we call the shell_notifyicon function to delete the icon in the system tray. This time we want to specify the NIM_DELETE message. Let's restore the main window to the original state. If the user selects the exit menu item, we not only give the icon to delete it, but also exit from the entire application.