首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

使用線程實現動態圖標切換,替代 SetTimer 的高效方案

     編輯:關於VC++

前言

在 MFC 開發中,若要在視窗標題欄顯示動態圖示,傳統做法是使用 SetTimer 配合 OnTimer 週期性更換圖示。但這種方式不僅程式碼繁瑣,還會佔用系統定時器資源。本文介紹一種將動畫邏輯封裝於獨立執行緒的 CAnimateIcon 類,只需兩行程式碼即可啟動動畫,大幅簡化開發流程。

核心設計思路

原作者唐星彬的文章採用 SetTimer 觸發 OnTimer 切換圖示。本方案改為:

  • 建立一個工作執行緒,在迴圈中依間隔時間切換圖示
  • 將執行緒邏輯封裝於 CAnimateIcon 類別內部
  • 對外僅暴露 SetImageList(載入圖示資源)與 Draw(啟動動畫)兩個介面

關鍵類別結構

class CAnimateIcon {
protected:
    CImageList m_imgList;      // 圖示列表
    int m_iImageCounter;       // 目前圖示索引
    int m_nMaxNumOfImages;     // 圖示總數
    bool m_bExit;              // 執行緒結束旗標
    CWnd* m_pWnd;              // 擁有圖示的視窗指標
    DWORD m_dwMilliseconds;    // 刷新間隔(毫秒)

public:
    CAnimateIcon();
    ~CAnimateIcon();
    bool SetImageList(int nResourceID, int nCount, COLORREF crTransparent);
    BOOL Draw(CWnd* pWnd, DWORD dwInterval = 1000);
    void ChangeInterval(DWORD dwTimes);

protected:
    static UINT WINAPI _ThreadAnimation(LPVOID pParam);
};

核心實現細節

啟動動畫 Draw()

BOOL CAnimateIcon::Draw(CWnd* pWnd, DWORD dwTimes) {
    m_pWnd = pWnd;
    ASSERT(m_pWnd);
    m_dwMilliseconds = dwTimes;

    unsigned int nThreadID;
    HANDLE hThread = (HANDLE)_beginthreadex(
        NULL, 0, _ThreadAnimation, this,
        CREATE_SUSPENDED, &nThreadID
    );

    if (!hThread) {
        TRACE(_T("Draw: Couldn't start ICON animation thread\n"));
        return FALSE;
    }
    ResumeThread(hThread);
    CloseHandle(hThread); // 不再需要句柄,立即關閉
    return TRUE;
}

執行緒主體 _ThreadAnimation()

UINT WINAPI CAnimateIcon::_ThreadAnimation(LPVOID pParam) {
    CAnimateIcon& self = *(CAnimateIcon*)pParam;

    while (!self.m_bExit) {
        if (self.m_imgList.m_hImageList == NULL) return 0;

        self.m_iImageCounter++;
        if (self.m_iImageCounter >= self.m_nMaxNumOfImages)
            self.m_iImageCounter = 0;

        HICON hIcon = self.m_imgList.ExtractIcon(self.m_iImageCounter);
        HICON hPrevIcon = (HICON)self.m_pWnd->SetIcon(hIcon, FALSE);
        DestroyIcon(hPrevIcon); // 釋放舊圖示資源

        Sleep(self.m_dwMilliseconds);
    }
    return 1;
}

使用範例

在視窗類別中宣告成員變數:

CAnimateIcon m_animIcon;

於 OnInitDialog 或 OnCreate 中初始化並啟動:

m_animIcon.SetImageList(IDB_BITMAP_ANIM, 6, RGB(0,0,0));
m_animIcon.Draw(this); // 預設 1000ms 間隔

若需調整速度,可呼叫 m_animIcon.ChangeInterval(500); 設為 500ms。

優勢總結

  • 零定時器佔用:不佔用系統有限的 SetTimer 資源
  • 封裝完善:外部無需處理 WM_TIMER 訊息
  • 資源自動管理:執行緒結束旗標 m_bExit 可於解構子中設定,確保乾淨退出
  • 相容性佳:VC6.0 + Win2000 SP3 編譯通過,亦適用於新版 Visual Studio

注意事項

  1. 圖示資源必須為同尺寸、同色深的位圖條(CImageList 要求)
  2. 透明色參數需與位圖實際背景色一致
  3. 視窗銷毀前應確保執行緒已結束,避免存取已釋放的 m_pWnd

完整原始碼請參考本文配套下載。此方案同樣適用於工具列按鈕、系統托盤圖示等需動態切換圖示的場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved