系統托盤位於 Windows 9x 工作列的一角,技術上稱為「工作列通知區」。許多軟體(如金山詞霸 III)運行時會在托盤放置圖示,讓使用者一眼看出程式正在背景執行,單擊圖示即可喚醒,極為方便。托盤程式設計雖特殊但不難,核心包含三大要素:圖示、工具提示、訊息處理,屬於 Shell 程式設計範疇。
Shell API 提供 Shell_NotifyIcon 函數,用於新增、刪除、修改托盤圖示。托盤圖示建立後,Windows Shell 會負責將滑鼠事件通知應用程式。
WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(DWORD dwMessage, PNOTIFYICONDATA pnid);
dwMessage:操作類型——NIM_ADD(新增)、NIM_DELETE(刪除)、NIM_MODIFY(修改圖示或提示文字)。pnid:指向 NOTIFYICONDATA 結構的指標,定義如下:typedef struct _NOTIFYICONDATA {
DWORD cbSize; // 結構大小,必須初始化為 sizeof(NOTIFYICONDATA)
HWND hWnd; // 接收托盤圖示訊息的視窗控制代碼
UINT uID; // 應用程式自訂的圖示 ID
UINT uFlags; // 指定哪些欄位有效:
// NIF_ICON - hIcon 有效,可修改圖示
// NIF_MESSAGE - uCallbackMessage 有效,定義回呼訊息
// NIF_TIP - szTip 有效,可修改工具提示
UINT uCallbackMessage; // 應用程式自訂的回呼訊息
HICON hIcon; // 托盤圖示控制代碼
char szTip[64]; // 工具提示文字
} NOTIFYICONDATA;
程式啟動時不顯示主視窗,僅在托盤顯示圖示,雙擊圖示關閉程式。
Timer 元件。Unit1.h,加入 #include <shellapi.h>。TForm1 的 private 區段宣告資料成員與方法:unsigned int iconmessage; // 自訂訊息
void AddTrayIcon(); // 新增托盤圖示
void RemoveTrayIcon(); // 移除托盤圖示
WndProc,在 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();
}
此處透過 RegisterWindowMessage 定義唯一使用者訊息,亦可用 WM_USER + n 取得未被系統使用的訊息編號。
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);
}
從主選單選擇 View | Project Source,在 WinMain 的 Application->Initialize() 之後加入:
ShowWindow(Application->Handle, SW_HIDE);
Application->ShowMainForm = false;
按 F9 編譯執行,托盤即會出現圖示。程式碼在 C++ Builder 3 / Windows 98 環境下測試通過。