系統托盤在我們使用的程序中很普遍,下面我們來看一個很不錯的例子,使用Win32 API實現,對理解系統托盤有些幫助。
#include <windows.h> #define IDR_PAUSE 12 #define IDR_START 13 /* #include <shellapi.h> #pragma comment(lib, "shell32.lib") */ LPCTSTR szAppName = TEXT("服務程序"); LPCTSTR szWndName = TEXT("服務程序"); HMENU hmenu;//菜單句柄 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { NOTIFYICONDATA nid; UINT WM_TASKBARCREATED; POINT pt;//用於接收鼠標坐標 int xx;//用於接收菜單選項返回值 // 不要修改TaskbarCreated,這是系統任務欄自定義的消息 WM_TASKBARCREATED = RegisterWindowMessage(TEXT("TaskbarCreated")); switch (message) { case WM_CREATE://窗口創建時候的消息. nid.cbSize = sizeof(nid); nid.hWnd = hwnd; nid.uID = 0; nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nid.uCallbackMessage = WM_USER; nid.hIcon = LoadIcon(NULL, IDI_APPLICATION); lstrcpy(nid.szTip, szAppName); Shell_NotifyIcon(NIM_ADD, &nid); hmenu=CreatePopupMenu();//生成菜單 AppendMenu(hmenu,MF_STRING,IDR_PAUSE,"暫停服務");//為菜單添加兩個選項 AppendMenu(hmenu,MF_STRING,IDR_START,"恢復服務"); break; case WM_USER://連續使用該程序時候的消息. if (lParam == WM_LBUTTONDOWN) MessageBox(hwnd, TEXT("Win32 API 實現系統托盤程序,雙擊托盤可以退出!"), szAppName, MB_OK); if (lParam == WM_LBUTTONDBLCLK)//雙擊托盤的消息,退出. SendMessage(hwnd, WM_CLOSE, wParam, lParam); if (lParam == WM_RBUTTONDOWN) { GetCursorPos(&pt);//取鼠標坐標 ::SetForegroundWindow(hwnd);//解決在菜單外單擊左鍵菜單不消失的問題 EnableMenuItem(hmenu,IDR_PAUSE,MF_GRAYED);//讓菜單中的某一項變灰 xx=TrackPopupMenu(hmenu,TPM_RETURNCMD,pt.x,pt.y,NULL,hwnd,NULL);//顯示菜單並獲取選項ID if(xx==IDR_PAUSE) MessageBox(hwnd, TEXT("111"), szAppName, MB_OK); if(xx==IDR_START) MessageBox(hwnd, TEXT("222"), szAppName, MB_OK); if(xx==0) PostMessage(hwnd,WM_LBUTTONDOWN,NULL,NULL); //MessageBox(hwnd, TEXT("右鍵"), szAppName, MB_OK); } break; case WM_DESTROY://窗口銷毀時候的消息. Shell_NotifyIcon(NIM_DELETE, &nid); PostQuitMessage(0); break; default: /* * 防止當Explorer.exe 崩潰以後,程序在系統系統托盤中的圖標就消失 * * 原理:Explorer.exe 重新載入後會重建系統任務欄。當系統任務欄建立的時候會向系統內所有 * 注冊接收TaskbarCreated 消息的頂級窗口發送一條消息,我們只需要捕捉這個消息,並重建系 * 統托盤的圖標即可。 */ if (message == WM_TASKBARCREATED) SendMessage(hwnd, WM_CREATE, wParam, lParam); break; } return DefWindowProc(hwnd, message, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow) { HWND hwnd; MSG msg; WNDCLASS wndclass; HWND handle = FindWindow(NULL, szWndName); if (handle != NULL) { MessageBox(NULL, TEXT("Application is already running"), szAppName, MB_ICONERROR); return 0; } wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } // 此處使用WS_EX_TOOLWINDOW 屬性來隱藏顯示在任務欄上的窗口程序按鈕 hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, szAppName, szWndName, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }