在 Windows 系統右下角通知區域(System Tray)顯示動畫圖示,能直觀反映應用程式狀態(如網路傳輸、備份進度、郵件接收)。本文示範如何在 C++Builder 中利用 TTimer 與 Shell_NotifyIcon API 實作幀動畫效果,以「門開關」動畫為例。
Windows 透過 Shell_NotifyIcon 管理托盤圖示,支援三種操作:
NIM_ADD:新增圖示NIM_MODIFY:更新圖示(動畫關鍵)NIM_DELETE:移除圖示函數原型:
WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(
DWORD dwMessage, // NIM_ADD / NIM_MODIFY / NIM_DELETE
PNOTIFYICONDATA lpData // 圖示資料結構
);
定義圖示行為與外觀的核心結構體:
typedef struct _NOTIFYICONDATA {
DWORD cbSize; // 結構大小
HWND hWnd; // 接收回呼訊息的視窗
UINT uID; // 圖示識別碼
UINT uFlags; // 有效欄位旗標 (NIF_MESSAGE|NIF_ICON|NIF_TIP)
UINT uCallbackMessage; // 自訂回呼訊息 (如 WM_USER+1)
HICON hIcon; // 圖示控制代碼
TCHAR szTip[128]; // 滑鼠懸停提示文字
// ... 後續版本擴充欄位
} NOTIFYICONDATA, *PNOTIFYICONDATA;
TTimer (Timer1),設定 Interval = 1000 (1 秒/幀)TImage (Image1, Image2),分別載入「開門」、「關門」圖示 (.ico 格式)int n = 1; 控制幀切換bool __fastcall TForm1::TrayMessage(DWORD dwMessage) {
NOTIFYICONDATA tnd = {0};
tnd.cbSize = sizeof(NOTIFYICONDATA);
tnd.uCallbackMessage = MYWM_NOTIFY; // 自訂訊息常數
tnd.hWnd = Handle;
tnd.uID = IDC_MYICON;
tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
if (dwMessage == NIM_MODIFY) {
tnd.hIcon = IconHandle(); // 取得當前幀圖示
PSTR pszTip = TipText(); // 取得提示文字
if (pszTip)
lstrcpyn(tnd.szTip, pszTip, sizeof(tnd.szTip));
else
tnd.szTip[0] = '\0';
} else {
tnd.hIcon = NULL;
tnd.szTip[0] = '\0';
}
return Shell_NotifyIcon(dwMessage, &tnd);
}
HICON __fastcall TForm1::IconHandle(void) {
if (n == 1)
return Image1->Picture->Icon->Handle;
else
return Image2->Picture->Icon->Handle;
}
void __fastcall TForm1::ToggleState(void) {
n = (n == 1) ? 0 : 1; // 在 0、1 間切換
TrayMessage(NIM_MODIFY); // 通知系統更新圖示
}
void __fastcall TForm1::Timer1Timer(TObject *Sender) {
ToggleState(); // 每秒觸發一次幀切換
}
void __fastcall TForm1::FormCreate(TObject *Sender) {
TrayMessage(NIM_ADD); // 程式啟動時加入托盤
Timer1->Enabled = true;
}
void __fastcall TForm1::FormDestroy(TObject *Sender) {
Timer1->Enabled = false;
TrayMessage(NIM_DELETE); // 程式結束時移除
}
Interval 設定 100-200ms 可獲得較流暢動畫,但會增加 CPU 佔用。HICON) 需配對 DestroyIcon 釋放,但 TImage::Picture::Icon::Handle 由 VCL 管理,手動釋放會導致重複釋放錯誤。處理自訂回呼訊息 (MYWM_NOTIFY) 可實作:
void __fastcall TForm1::WmNotifyIcon(TMessage &Msg) {
switch (Msg.LParam) {
case WM_LBUTTONDOWN:
Visible = !Visible; // 切換視窗顯示
break;
case WM_RBUTTONDOWN:
PopupMenu1->Popup(Mouse->CursorPos.X, Mouse->CursorPos.Y);
break;
}
}
將上述邏輯整合後,專案結構如下:
FormCreate、FormDestroy、Timer1Timer、TrayMessage、IconHandle、ToggleState、WmNotifyIcon 實作door_open.ico、door_close.ico透過 Shell_NotifyIcon 配合定時器輪詢更新圖示,即可在 C++Builder 中輕鬆實作托盤動畫。此技術廣泛應用於即時通訊軟體、系統監控工具、備份程式等需長駐後台並提供視覺回饋的應用。開發者可根據需求擴充幀數、加入互動選單、整合應用程式狀態機,打造專業級使用者體驗。