系统托盘图标
系统托盘图标的创建主要使用 Shell_NotifyIcon 函数来实现,实现过程比较简单。
注意:
要创建系统托盘图标,必须要有窗口;要创建窗口,必须要有窗口过程函数。
一个窗口可以有多个系统托盘图标;图标彼此间用 hWnd 和 uID 区分;
窗口过程函数接收到事件后, wParam 表示 uID,lParam 表示 message;
以下是封装的托盘类代码:
// notifyicon.h
#ifndef _NOTIFYICON_H_ #define _NOTIFYICON_H_ #include <windows.h> #include <shellapi.h> #include <map> typedef VOID (*NotifyIconCallback) (UINT uID, UINT message); class NotifyIcon { public: static UINT AddIcon(HICON hIcon, WCHAR* szTip); static VOID DelIcon(UINT uID); static VOID ModIcon(UINT uID, HICON hIcon, WCHAR* szTip); static UINT Attach(NotifyIconCallback pCallback); static VOID Detach(UINT uCookie); private: static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); private: static HWND m_hWnd; static UINT m_uCookieCount; static std::map<UINT,NotifyIconCallback> m_mapCallback; static UINT m_uIDCount; static std::map<UINT,NOTIFYICONDATA> m_mapNotifyData; }; #endif
// notifyicon.cpp
#include "notifyicon.h" HWND NotifyIcon::m_hWnd = NULL; UINT NotifyIcon::m_uCookieCount = 0; std::map<UINT,NotifyIconCallback> NotifyIcon::m_mapCallback; UINT NotifyIcon::m_uIDCount = 0; std::map<UINT,NOTIFYICONDATA> NotifyIcon::m_mapNotifyData; UINT NotifyIcon::AddIcon( HICON hIcon, WCHAR* szTip ) { // 创建窗口 LPCTSTR pszClassName = TEXT("NotifyIcon_ClassName"); LPCTSTR pszWndName = TEXT("NotifyIcon_WndName"); HINSTANCE hInstance = GetModuleHandle(NULL); WNDCLASS wndClass; if (GetClassInfo(hInstance, pszClassName, &wndClass) == 0) { wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = NotifyIcon::WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = NULL; wndClass.hCursor = NULL; wndClass.hbrBackground = NULL; wndClass.lpszClassName = pszClassName; wndClass.lpszMenuName = NULL; if (RegisterClass(&wndClass) == NULL) { return NULL; } } if (FindWindow(pszClassName, pszWndName) == NULL) { m_hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, pszClassName, pszWndName, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (m_hWnd == NULL) { return NULL; } } UINT uID = m_uIDCount; m_uIDCount++; NOTIFYICONDATA nd; nd.cbSize = sizeof(nd); nd.hWnd = m_hWnd; nd.uID = uID; nd.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nd.uCallbackMessage = WM_USER; nd.hIcon = hIcon; if (szTip != NULL && lstrlen(szTip) < 127) { lstrcpy(nd.szTip, szTip); } if(Shell_NotifyIcon(NIM_ADD, &nd) == TRUE) { m_mapNotifyData.insert(std::make_pair(uID, nd)); return uID; } return NULL; } VOID NotifyIcon::DelIcon( UINT uID ) { if (m_hWnd == NULL) { return; } std::map<UINT, NOTIFYICONDATA>::iterator iter = m_mapNotifyData.find(uID); if (iter != m_mapNotifyData.end()) { Shell_NotifyIcon(NIM_DELETE, &(iter->second)); m_mapNotifyData.erase(iter); } } VOID NotifyIcon::ModIcon( UINT uID, HICON hIcon, WCHAR* szTip ) { if (m_hWnd == NULL) { return; } std::map<UINT, NOTIFYICONDATA>::iterator iter = m_mapNotifyData.find(uID); if (iter != m_mapNotifyData.end()) { if (hIcon != NULL) { iter->second.hIcon = hIcon; } if (szTip && lstrlen(szTip) < 127) { lstrcpy(iter->second.szTip, szTip); } else { lstrcpy(iter->second.szTip, L""); } Shell_NotifyIcon(NIM_MODIFY, &(iter->second)); } } UINT NotifyIcon::Attach( NotifyIconCallback pCallback ) { if (pCallback == NULL) { return NULL; } UINT uCookie = m_uCookieCount; m_uCookieCount ++; m_mapCallback.insert(std::make_pair(uCookie, pCallback)); return uCookie; } VOID NotifyIcon::Detach( UINT uCookie ) { std::map<UINT, NotifyIconCallback>::iterator iter = m_mapCallback.find(uCookie); if (iter != m_mapCallback.end()) { m_mapCallback.erase(iter); } } LRESULT CALLBACK NotifyIcon::WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch(message) { case WM_CREATE: break; case WM_DESTROY: break; case WM_USER: for (std::map<UINT, NotifyIconCallback>::iterator iter = m_mapCallback.begin(); iter != m_mapCallback.end(); ++iter) { NotifyIconCallback pCallback = iter->second; pCallback(wParam, lParam); // wParam --> uID, lParam --> message } break; default: break; } return DefWindowProc(hwnd, message, wParam, lParam); }
// main.cpp 测试
#include <windows.h> #include "notifyicon.h" void callbackFunc(UINT uID, UINT message); int main() { HINSTANCE hInstance = GetModuleHandle(NULL); HICON hIcon = LoadIcon(hInstance, IDI_APPLICATION); WCHAR szTip[128] = L"哈哈哈"; UINT uID1 = NotifyIcon::AddIcon(hIcon, szTip); UINT uID2 = NotifyIcon::AddIcon(hIcon, szTip); UINT uID3 = NotifyIcon::AddIcon(hIcon, szTip); NotifyIcon::ModIcon(uID3, hIcon, NULL); NotifyIcon::DelIcon(uID2); UINT uCookie = NotifyIcon::Attach(callbackFunc); NotifyIcon::Detach(uCookie); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } void callbackFunc(UINT uID, UINT message) { if (message == WM_LBUTTONDOWN || message == WM_LBUTTONUP || message == WM_LBUTTONDBLCLK || message == WM_RBUTTONDOWN || message == WM_RBUTTONUP || message == WM_RBUTTONDBLCLK) { WCHAR szDbg[256]; ZeroMemory(szDbg,256); wsprintf(szDbg, L"[Dongyu] uID = %d, message = %x", uID, message); OutputDebugString(szDbg); } }
参考文章: