Windows 95 任務列(Taskbar)右側的狀態區(通知區)可顯示輸入法、時間、列印管理員等圖示。應用程式可在此放置自訂圖示,指示背景程式運作狀態,並提供滑鼠點擊互動介面。核心 API 為 Shell_NotifyIcon。
typedef struct _NOTIFYICONDATA {
DWORD cbSize; // 結構大小,必須初始化
HWND hWnd; // 接收訊息的視窗控制碼
UINT uID; // 圖示識別碼,可放多個圖示
UINT uFlags; // 指定後續欄位有效性:NIF_MESSAGE|NIF_ICON|NIF_TIP
UINT uCallbackMessage; // 自訂回呼訊息代碼
HICON hIcon; // 圖示控制碼
char szTip[64]; // 滑鼠懸停提示文字
} NOTIFYICONDATA;
皆呼叫 Shell_NotifyIcon,第一參數為操作代碼:NIM_ADD 新增,NIM_DELETE 刪除。
BOOL AddTaskBarIcon(HWND hWnd, UINT uID, HICON hIcon, LPSTR lpszTip)
{
BOOL res;
NOTIFYICONDATA nid = {0};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = uID;
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
nid.uCallbackMessage = MYWM_NOTIFYICON; // 自訂訊息
nid.hIcon = hIcon;
if (lpszTip)
lstrcpyn(nid.szTip, lpszTip, sizeof(nid.szTip));
else
nid.szTip[0] = '\0';
res = Shell_NotifyIcon(NIM_ADD, &nid);
if (hIcon) DestroyIcon(hIcon); // 圖示資源由系統管理,此處可釋放
return res;
}
BOOL DeleteTaskBarIcon(HWND hWnd, UINT uID)
{
NOTIFYICONDATA nid = {0};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = uID;
return Shell_NotifyIcon(NIM_DELETE, &nid);
}
狀態區圖示接收滑鼠事件後,將封裝在自訂訊息(uCallbackMessage)中傳送給 hWnd 的視窗程序。wParam 為圖示 ID (uID),lParam 為滑鼠訊息代碼(如 WM_LBUTTONDOWN、WM_RBUTTONDBLCLK 等)。
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case MYWM_NOTIFYICON:
OnNotifyIcon(wParam, lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
void OnNotifyIcon(WPARAM wParam, LPARAM lParam)
{
UINT uID = (UINT)wParam;
UINT uMouseMsg = (UINT)lParam;
if (uMouseMsg == WM_LBUTTONDOWN) {
MessageBox(NULL, "Be happy, don't worry.", "TaskBarIcon", MB_OK);
}
// 可擴充處理右鍵選單、雙擊等
}
cbSize 必須正確設定,否則 API 失敗。uCallbackMessage 建議用 RegisterWindowMessage 產生唯一值,避免衝突。hIcon) 在 NIM_ADD 後由系統複製管理,原控制碼可釋放;但 NIM_MODIFY 更換圖示時需提供新控制碼。uID 放置多個圖示。NIM_DELETE 移除圖示,否則殘留圖示需重新啟動 Explorer 才能清除。