系統匣是 Windows 任務列上的特殊區域(技術名稱:「任務列通知區域」),許多常駐程式(如輸入法、防毒軟體)會在此放置圖示,讓使用者一眼知曉程式正在背景執行,並能快速喚醒。系統匣程式開發屬於 Shell 程式設計範疇,核心在於 Shell_NotifyIcon API 函數。
typedef struct _NOTIFYICONDATA {
DWORD cbSize; // 結構大小,必須初始化
HWND hWnd; // 接收訊息的視窗控制代碼
UINT uID; // 應用程式定義的圖示 ID
UINT uFlags; // 有效欄位標誌:NIF_ICON、NIF_MESSAGE、NIF_TIP
UINT uCallbackMessage; // 自訂回呼訊息
HICON hIcon; // 圖示控制代碼
char szTip[64]; // 工具提示文字
} NOTIFYICONDATA;
BOOL WINAPI Shell_NotifyIcon(DWORD dwMessage, PNOTIFYICONDATA pnid);
dwMessage 操作類型:NIM_ADD(新增)、NIM_DELETE(刪除)、NIM_MODIFY(修改圖示或提示)。
#include <shellapi.h>
// ...
private:
unsigned int iconMessage; // 自訂訊息編號
void AddTrayIcon(); // 新增匣圖示
void RemoveTrayIcon(); // 移除匣圖示
protected:
virtual void __fastcall WndProc(Messages::TMessage &Message); // 重載視窗程序
void TForm1::AddTrayIcon() {
NOTIFYICONDATA icondata;
memset(&icondata, 0, sizeof(icondata));
icondata.cbSize = sizeof(icondata);
icondata.hWnd = Handle;
strncpy(icondata.szTip, "未知狀態", sizeof(icondata.szTip));
icondata.hIcon = Application->Icon->Handle;
icondata.uCallbackMessage = iconMessage;
icondata.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
Shell_NotifyIcon(NIM_ADD, &icondata);
}
void TForm1::RemoveTrayIcon() {
NOTIFYICONDATA icondata;
memset(&icondata, 0, sizeof(icondata));
icondata.cbSize = sizeof(icondata);
icondata.hWnd = Handle;
Shell_NotifyIcon(NIM_DELETE, &icondata);
}
void __fastcall TForm1::WndProc(Messages::TMessage &Message) {
if (Message.Msg == iconMessage) {
if (Message.LParam == WM_LBUTTONDBLCLK) {
Application->Terminate(); // 雙擊關閉程式
}
return;
}
TForm::WndProc(Message); // 其他訊息交給基底類別處理
}
void __fastcall TForm1::FormCreate(TObject *Sender) {
iconMessage = RegisterWindowMessage("IconNotify"); // 註冊唯一訊息
AddTrayIcon();
}
void __fastcall TForm1::FormDestroy(TObject *Sender) {
RemoveTrayIcon(); // 關閉時移除匣圖示
}
void __fastcall TForm1::Timer1Timer(TObject *Sender) {
NOTIFYICONDATA icondata;
memset(&icondata, 0, sizeof(icondata));
icondata.cbSize = sizeof(icondata);
icondata.hWnd = Handle;
String s = "我的圖示!";
strncpy(icondata.szTip, s.c_str(), sizeof(icondata.szTip));
icondata.uFlags = NIF_TIP;
Shell_NotifyIcon(NIM_MODIFY, &icondata);
}
在專案原始碼 WinMain 中 Application->Initialize() 之後加入:
ShowWindow(Application->Handle, SW_HIDE);
Application->ShowMainForm = false;
RegisterWindowMessage 取得唯一訊息編號,避免衝突。WndProc 攔截 uCallbackMessage,處理滑鼠事件(WM_LBUTTONDBLCLK、WM_RBUTTONDOWN 等)。NIM_DELETE 清理匣圖示,否則會留下「殭屍圖示」。Application->Icon->Handle) 或載入自訂 .ico 檔。掌握 Shell_NotifyIcon 機制,即可開發出專業級的常駐系統匣應用程式,提升使用者體驗與程式可見性。