想讓應用程式標題列圖示「動」起來嗎?本文示範如何在 VC++ 6.0 的 SDI 專案中,利用 CImageList 管理多幀位圖,配合 SetTimer() 週期性切換圖示,打造標題列動畫效果。完整步驟與原始碼供參考。
WndStyle。IDB_ANIM_IMGLIST。新增 AnimateIcon.h/cpp 至專案,封裝圖示清單建立與幀切換邏輯:
// AnimateIcon.h
class CAnimateIcon {
protected:
CImageList m_imgList;
int m_iImageCounter = -1;
int m_iMaxNoOfImages = -99;
HICON hIcon, hPrevIcon;
public:
CAnimateIcon(); ~CAnimateIcon();
BOOL SetImageList(int nResID, int nCount, COLORREF crTransparent);
BOOL ShowNextImage();
};
// AnimateIcon.cpp 關鍵實作
BOOL CAnimateIcon::SetImageList(int nResID, int nCount, COLORREF crTransparent) {
if (nCount <= 0) return FALSE;
m_iMaxNoOfImages = nCount;
return m_imgList.Create(nResID, 16, 1, crTransparent); // 16x16, 1幀寬度
}
BOOL CAnimateIcon::ShowNextImage() {
if (!m_imgList.m_hImageList) return FALSE;
m_iImageCounter = (m_iImageCounter + 1) % m_iMaxNoOfImages;
hIcon = m_imgList.ExtractIcon(m_iImageCounter);
// 發送 WM_SETICON 更新主視窗圖示
hPrevIcon = (HICON)AfxGetMainWnd()->SendMessage(WM_SETICON, TRUE, (LPARAM)hIcon);
if (hPrevIcon) DestroyIcon(hPrevIcon); // 釋放前一個圖示資源
return TRUE;
}
// MainFrm.h
#include "AnimateIcon.h"
class CMainFrame : public CFrameWnd {
protected:
CAnimateIcon m_animIcon;
UINT m_timerID;
// ...
};
// MainFrm.cpp OnCreate
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
m_animIcon.SetImageList(IDB_ANIM_IMGLIST, 4, RGB(0,0,0)); // 黑色透明
m_timerID = SetTimer(99, 100, NULL); // 100ms 切換一次
return 0;
}
// 訊息處理
void CMainFrame::OnTimer(UINT nIDEvent) {
m_animIcon.ShowNextImage();
CFrameWnd::OnTimer(nIDEvent);
}
void CMainFrame::OnDestroy() {
if (m_timerID) KillTimer(m_timerID);
CFrameWnd::OnDestroy();
}
編譯執行後,應用程式標題列左上角圖示將以 100ms 間隔循環播放 4 幀動畫,效果流暢且資源佔用極低。
LoadImage() 從檔案動態載入圖示,支援使用者自訂主題。CDialog 衍生類別中同樣處理 WM_SETICON。利用 CImageList 管理多幀圖示、ExtractIcon() 擷取單幀、WM_SETICON 更新視窗圖示、定時器驅動幀切換,四步即可實現標題列動畫。技術簡單卻能顯著提升軟體專業感與辨識度。