同系統托盤開發,關鍵在於 **NIM_ADD 新增**、**NIM_MODIFY 修改**、**NIM_DELETE 移除** 三操作,配合自訂回呼訊息處理滑鼠事件。
// 自訂回呼訊息
#define WM_MYTRAYICON (WM_APP + 100)
void PutToTaskBar(HWND hwnd, UINT uId, HICON hIcon, LPCTSTR tip) {
NOTIFYICONDATA nid = { sizeof(nid) };
nid.hWnd = hwnd; nid.uID = uId; nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
nid.uCallbackMessage = WM_MYTRAYICON; nid.hIcon = hIcon;
lstrcpyn(nid.szTip, tip, 128);
Shell_NotifyIcon(NIM_ADD, &nid); // 新增
Shell_NotifyIcon(NIM_MODIFY, &nid); // 確保圖示/提示生效
}
BOOL TrayMessage(HWND hwnd, DWORD msg, UINT uId, HICON hIcon, LPCTSTR tip) {
NOTIFYICONDATA nid = { sizeof(nid) };
nid.hWnd = hwnd; nid.uID = uId; nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
nid.uCallbackMessage = WM_MYTRAYICON; nid.hIcon = hIcon;
lstrcpyn(nid.szTip, tip, 128);
BOOL res = Shell_NotifyIcon(msg, &nid);
if (hIcon) DestroyIcon(hIcon); // 圖示控制代碼由呼叫端管理
return res;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
if (msg == WM_MYTRAYICON) {
switch (lp) {
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
// 雙擊還原主視窗
ShowWindow(hwnd, SW_RESTORE);
SetForegroundWindow(hwnd);
break;
case WM_RBUTTONDOWN:
// 右鍵彈出選單
POINT pt; GetCursorPos(&pt);
SetForegroundWindow(hwnd);
TrackPopupMenu(hPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
break;
}
return 0;
}
// ... 其他訊息
return DefWindowProc(hwnd, msg, wp, lp);
}
void __fastcall TForm1::FormResize(TObject* Sender) {
if (WindowState == wsMinimized) {
ShowWindow(Handle, SW_HIDE); // 隱藏任務列按鈕
PutToTaskBar(Handle, 1, Application->Icon->Handle, "我的程式");
}
}
void __fastcall TForm1::OnTrayRestore(TObject* Sender) {
ShowWindow(Handle, SW_RESTORE);
WindowState = wsNormal;
TrayMessage(Handle, NIM_DELETE, 1, NULL, NULL); // 移除托盤圖示
}
WS_EX_TOOLWINDOWWS_EX_TOOLWINDOW:**不在任務列顯示按鈕**,Alt+Tab 不切換,適合純托盤程式。SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TOOLWINDOW)。Icons、Hint、Animate、PopupMenu。OnClick (單擊)、OnDblClick (雙擊還原)、OnMouseDown (右鍵選單)。| 問題 | 解決 |
|---|---|
| 最小化後無法還原 | 檢查 FormResize 邏輯、托盤雙擊事件是否正確 ShowWindow/Restore |
| 托盤圖示重複/殘留 | 確保 FormDestroy/關閉時呼叫 NIM_DELETE,處理 WM_TASKBARCREATED 重建 |
| 右鍵選單不消失/失焦 | TrackPopupMenu/PopupMenu->Popup 前呼叫 SetForegroundWindow(Handle) |
| 管理員權限下托盤不顯示 | 高完整性進程托盤圖示需在相同會話,或用服務+UI 分離架構 |