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

Windows 計時器多重應用實作指南:SetTimer/KillTimer 完整解析

     編輯:關於VC++

計時器基本使用方法

程式設計常需計時器,Windows 提供兩種實作方式:發送 WM_TIMER 訊息、呼叫應用程式定義的回呼函式。

方法一:WM_TIMER 訊息機制

SetTimer API 原型

UINT_PTR SetTimer(
    HWND hWnd,            // 視窗控制代碼
    UINT_PTR nIDEvent,    // 計時器 ID,多計時器時識別用
    UINT uElapse,         // 間隔毫秒數
    TIMERPROC lpTimerFunc // 回呼函式,NULL 表示用 WM_TIMER

使用範例

// 1 秒觸發一次
SetTimer(hWnd, 1, 1000, NULL);

// MFC 封裝 (CWnd::SetTimer)
UINT id = SetTimer(1, 100, NULL);  // 100ms,回傳 ID

注意事項

  • 間隔時間若短於處理時間,程式會出現問題(重入、堆疊溢位)
  • WM_TIMER 為低優先序訊息,訊息佇列擁塞時會延遲
  • 非精確計時,受系統負載影響

方法二:回呼函式機制

回呼函式原型

void CALLBACK TimerProc(
    HWND hWnd,      // 視窗控制代碼
    UINT nMsg,      // 訊息 (WM_TIMER)
    UINT nTimerID,  // 計時器 ID
    DWORD dwTime);  // 系統時間

建立計時器

SetTimer(1, 100, TimerProc);  // 第三參數傳入回呼函式位址

多計時器實作與應用

安裝計時器時指定 ID,多計時器透過 ID 識別。

非 MFC 環境:WM_TIMER 訊息處理

case WM_TIMER:
    switch (wParam)  // wParam 為計時器 ID
    {
        case 1:  HandleTimer1(); break;
        case 2:  HandleTimer2(); break;
    }
    break;

MFC 環境:OnTimer 處理

void CTimerTestDlg::OnTimer(UINT nIDEvent)
{
    switch (nIDEvent)
    {
        case 24:  Draw1(); break;  // ID 24 計時器
        case 25:  Draw2(); break;  // ID 25 計時器
    }
    CDialog::OnTimer(nIDEvent);
}

回呼函式模式識別計時器

void CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nTimerID, DWORD dwTime)
{
    switch (nTimerID)
    {
        case 1:  Do1(); break;
        case 2:  Do2(); break;
    }
}

取消計時器

不再使用時必須呼叫 KillTimer 釋放資源。

API 原型

BOOL KillTimer(
    HWND hWnd,          // 視窗控制代碼
    UINT_PTR uIDEvent); // 計時器 ID

MFC 封裝

KillTimer(nIDEvent);  // 直接傳入 ID

完整範例:雙計時器並行與自動停止

class CTimerDemoDlg : public CDialog
{
    int m_nTimer1Count;
    int m_nTimer2Count;

    virtual BOOL OnInitDialog()
    {
        CDialog::OnInitDialog();
        m_nTimer1Count = m_nTimer2Count = 0;
        SetTimer(1, 1000, NULL);  // 1 秒計時器
        SetTimer(2, 500, NULL);   // 0.5 秒計時器
        return TRUE;
    }

    void OnTimer(UINT nIDEvent)
    {
        switch (nIDEvent)
        {
            case 1:
                m_nTimer1Count++;
                UpdateTimerDisplay(1, m_nTimer1Count);
                if (m_nTimer1Count >= 10)
                    KillTimer(1);  // 執行 10 次後停止
                break;

            case 2:
                m_nTimer2Count++;
                UpdateTimerDisplay(2, m_nTimer2Count);
                break;
        }
        CDialog::OnTimer(nIDEvent);
    }
};

進階計時器技術對照

技術精度適用場景複雜度
SetTimer/WM_TIMER~10-15msUI 更新、輪詢、動畫低
Multimedia Timer (timeSetEvent)~1ms音訊、遊戲迴路中
Waitable Timer (CreateWaitableTimer)~0.5ms執行緒同步、精確排程中高
High-Resolution Timer (QueryPerformanceCounter)< 1μs效能分析、科學計算高
Timer Queue (CreateTimerQueueTimer)~1ms執行緒池排程、服務型應用中高

常見問題與最佳實務

  • 計時器 ID 衝突:使用 SetTimer(NULL, 0, ...) 讓系統自動分配唯一 ID
  • 重入風險:計時器處理函式執行時間超過間隔 → 使用關鍵區或旗標防護
  • 記憶體洩漏:視窗銷毀前未 KillTimer → OnDestroy 中清理所有計時器
  • 精度需求:UI 計時器不適合精確測量 → 改用 QueryPerformanceCounter
  • 電源管理:睡眠/休眠期間計時器行為差異 → 測試目標環境行為
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved