托盤圖標使用函數 Shell_NotifyIcon 建立、修改和刪除,參數主要使用 NOTIFYICONDATA 結構。windows
任務欄啓動時會給全部頂層窗口發送 TaskbarCreated 消息,因爲不一樣系統消息標識不同,因此須要使用 RegisterWindowMessage 向系統獲取消息標識。ide
程序在VS2015 Win32編譯經過,XP SP3測試經過。Win10氣泡無反應,或者我該用 NOTIFYICON_VERSION_4 ?但願哪位能告知一二……函數
最後發現Win10須要打開操做中心,而且容許應用通知,Win10已把氣泡消息整合到裏面去了。可憐偶調試了三天……測試
下面是簡介和本人被坑過的地方,其餘可查看VS自帶幫助。ui
1、定義:(概覽\(^o^)/)spa
BOOL Shell_NotifyIcon( _In_ DWORD dwMessage, _In_ PNOTIFYICONDATA lpdata );
其中 dwMessage 經常使用的選項以下:(其餘略\(^o^)/).net
NIM_ADD |
添加托盤圖標。指針 |
NIM_MODIFY |
修改圖標,也可彈出氣泡圖標。調試 |
NIM_DELETE |
刪除圖標,應在整個程序結束時也調用一次。code |
第二個參數爲指向 NOTIFYICONDATA 的指針,經常使用參數以下:(其餘再略\(^o^)/)
cbSize | NOTIFYICONDATA 佔用的空間大小,要注意必定要先判斷 Shell32.dll 版本號(除非你不想用於多個版本的系統),來對其賦值,具體見例程。 |
|||
hWnd | 窗口句柄。 |
|||
uID | 建立的圖標標識,與 hWnd 組合定位托盤圖標。 |
|||
hIcon | 圖標句柄,通常使用 LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32TEST)) 賦予。 |
|||
uVersion | 版本,Win2000後通常使用 NOTIFYICON_VERSION 保證兼容性,注意它與 uTimeout 共享內存(union), NOTIFYICON_VERSION_4 適用於Vista之後的系統。 |
|||
uTimeout | 氣泡自動消失的時間,Vista無效(VC2015幫助原文:【This member is deprecated as of Windows Vista. Notification display times are now based on system accessibility settings.】,我之前在Win7+VS2008測試時有效,因此不肯定Win7以上是否無效) |
|||
uCallbackMessage |
|
|||
uFlags | 標識,指出有效的成員而且指出托盤圖標顯示的方式, NIF_MESSAGE 使 uCallbackMessage 有效, NIF_ICON 使 hIcon 有效, NIF_TIP 使 szTip 有效, NIF_INFO 使 szInfo 、 szInfoTitle 、 dwInfoFlags 、 uTimeout 有效。 |
|||
szTip |
鼠標指向托盤圖標時顯示的提示消息,注意長度。 | |||
szInfo |
氣泡提示內容,注意長度。 | |||
szInfoTitle |
氣泡標題,爲空時 dwInfoFlags 無效,注意長度。 | |||
dwInfoFlags |
氣泡圖標,NIIF_NONE 表示無圖標,NIIF_INFO 表示【提示】,NIIF_WARNING 表示【警告】,NIIF_ERROR 表示【錯誤】。(其餘略\(^o^)/) |
2、例程:(仍是概覽\(^o^)/)
頭文件:
class CTrayIcon { public: CTrayIcon(); ~CTrayIcon(); BOOL CreateTray(HWND, HICON, UINT, LPCTSTR = _T("")); BOOL ChangeTray(LPCTSTR, UINT = 3000); BOOL DeleteTray(); private: ULONGLONG GetVersion(LPCTSTR); DWORD GetSize_NotifyIconData(); NOTIFYICONDATA m_Notify; };
獲取cbsize,這裏要特別注意,具體可參考《關於NOTIFYICONDATA的一些新特性》和《正確使用DllGetVersion》:
ULONGLONG CTrayIcon::GetVersion(LPCTSTR lpszDllName) { HINSTANCE hinstDll; ULONGLONG dwVersion = 0; hinstDll = LoadLibrary(lpszDllName); if (hinstDll) { DLLGETVERSIONPROC pDllGetVersion; pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion"); if (pDllGetVersion) { DLLVERSIONINFO dvi; HRESULT hr; ZeroMemory(&dvi, sizeof(dvi)); dvi.cbSize = sizeof(dvi); hr = (*pDllGetVersion)(&dvi); if (SUCCEEDED(hr)) { dwVersion = MAKEDLLVERULL(dvi.dwMajorVersion, dvi.dwMinorVersion, dvi.dwBuildNumber, dvi.dwPlatformID); } } FreeLibrary(hinstDll); } return dwVersion; } DWORD CTrayIcon::GetSize_NotifyIconData() { TCHAR lpszDllName[128]; GetWindowsDirectory(lpszDllName, _TRUNCATE); _tcsncat_s(lpszDllName, _T("\\System32\\Shell32.dll"), _TRUNCATE); ULONGLONG NIDdllVer = GetVersion(lpszDllName); // before windows 2000 if (NIDdllVer < MAKEDLLVERULL(5, 0, 0, 0)) { return NOTIFYICONDATA_V1_SIZE; } // Windows 2000 else if (NIDdllVer < MAKEDLLVERULL(6, 0, 0, 0)) { return NOTIFYICONDATA_V2_SIZE; } // Windows XP or 2003 else if (NIDdllVer < MAKEDLLVERULL(6, 0, 6000, 0)) { return NOTIFYICONDATA_V3_SIZE; } // Windows Vista and later else { return sizeof(NOTIFYICONDATA); } }
建立:
BOOL CTrayIcon::CreateTray(HWND hWnd, HICON hIcon, UINT uCallbackMessage, LPCTSTR szTitle) { m_Notify.cbSize = GetSize_NotifyIconData(); m_Notify.hIcon = hIcon; m_Notify.hWnd = hWnd; m_Notify.uCallbackMessage = uCallbackMessage; m_Notify.uVersion = NOTIFYICON_VERSION; m_Notify.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; m_Notify.uID = 1; _tcscpy_s(m_Notify.szTip, szTitle); return Shell_NotifyIcon(NIM_ADD, &m_Notify); }
氣泡:
BOOL CTrayIcon::ChangeTray(LPCTSTR msg, UINT uTimeout) { m_Notify.uFlags = NIF_INFO; m_Notify.dwInfoFlags = NIIF_NONE; // m_Notify.uTimeout = uTimeout; _tcscpy_s(m_Notify.szInfo, msg); return Shell_NotifyIcon(NIM_MODIFY, &m_Notify); }
刪除:
BOOL CTrayIcon::DeleteTray() { return Shell_NotifyIcon(NIM_DELETE, &m_Notify); }
定義托盤圖標響應消息:
#define WM_ICON_NOTIFY WM_USER+1001
註冊 TaskbarCreated 消息:
const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(_T("TaskbarCreated"));
消息處理&調用(Win32):
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // Restore the tray-icon after the explorer's recreation if (message == WM_TASKBARCREATED) { if (!IsWindowVisible(hWnd)) trayIcon.CreateTray(hWnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32TEST)), WM_ICON_NOTIFY, szTitle); return DefWindowProc(hWnd, message, wParam, lParam); } switch (message) { case WM_SIZE: switch (wParam) { case SIZE_RESTORED: // Restore the window and delete the tray-icon ShowWindow(hWnd, SW_SHOW); trayIcon.DeleteTray(); break; case SIZE_MINIMIZED: // Hide the window and create the tray-icon ShowWindow(hWnd, SW_HIDE); trayIcon.CreateTray(hWnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32TEST)), WM_ICON_NOTIFY, szTitle); break; default: break; } return DefWindowProc(hWnd, message, wParam, lParam); case WM_COMMAND: // ... break; case WM_PAINT: // ... break; case WM_ICON_NOTIFY: switch (lParam) { case WM_LBUTTONDOWN: SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, lParam); SetForegroundWindow(hWnd); break; default: break; } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }