利用 TTimer 定時觸發,在 OnTimer 事件中呼叫 Shell_NotifyIcon(NIM_MODIFY, ...) 切換 hIcon,形成動畫效果。關鍵:圖示資源預載、狀態機切換、資源釋放。
.ico (建議 16x16, 32x32 含多種色深)。Project → Resources) 或用 TImageList 載入。IDI_OPEN)、「關門」(IDI_CLOSE)。
int currentIcon = 0; // 0=開, 1=關
HICON hIcons[2]; // 圖示控制代碼陣列
UINT timerInterval = 1000; // 1 秒切換一次
void __fastcall TForm1::FormCreate(TObject* Sender) {
hIcons[0] = LoadIcon(HInstance, MAKEINTRESOURCE(IDI_OPEN));
hIcons[1] = LoadIcon(HInstance, MAKEINTRESOURCE(IDI_CLOSE));
NOTIFYICONDATA nid = { sizeof(nid) };
nid.hWnd = Handle; nid.uID = 1; nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
nid.uCallbackMessage = WM_MYTRAYICON; nid.hIcon = hIcons[0];
lstrcpyn(nid.szTip, "動畫托盤示範", 128);
Shell_NotifyIcon(NIM_ADD, &nid);
Timer1->Interval = timerInterval;
Timer1->Enabled = true;
}
void __fastcall TForm1::Timer1Timer(TObject* Sender) {
currentIcon = 1 - currentIcon; // 0↔1 切換
NOTIFYICONDATA nid = { sizeof(nid) };
nid.hWnd = Handle; nid.uID = 1; nid.uFlags = NIF_ICON;
nid.hIcon = hIcons[currentIcon];
Shell_NotifyIcon(NIM_MODIFY, &nid);
}
void __fastcall TForm1::FormDestroy(TObject* Sender) {
Timer1->Enabled = false;
Shell_NotifyIcon(NIM_DELETE, &(NOTIFYICONDATA){ sizeof(NOTIFYICONDATA), Handle, 1 });
if (hIcons[0]) DestroyIcon(hIcons[0]);
if (hIcons[1]) DestroyIcon(hIcons[1]);
}
Icons 集合 (多個 TIcon)。Animate = true, AnimateInterval = 1000 (ms)。| 問題 | 解決 |
|---|---|
| 動畫卡頓/不同步 | Timer 精度 ~10-15ms,接受;避免在 OnTimer 做耗時操作 |
| 圖示模糊/縮放失真 | 提供 16x16, 32x32, 48x48 多尺寸內嵌於 .ico |
| 資源洩漏 | FormDestroy 必須 DestroyIcon 所有 LoadIcon 取得的 HICON |
| Explorer 重啟圖示消失 | 處理 WM_TASKBARCREATED 重新 NIM_ADD |
| 高 DPI 模糊 | 啟用 Per-Monitor DPI Awareness,提供高解析度圖示 |