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

Win32 開發入門(24):計時器 - SetTimer/KillTimer 與 WM_TIMER 低優先級特性

     編輯:關於C++

Win32 計時器以 SetTimer/KillTimer 成對操作,透過 WM_TIMER 訊息或回呼函式通知。本文解析兩種模式差異、低優先級特性與閃爍視窗實作範例。

核心 API

UINT_PTR SetTimer(
    HWND hWnd,           // 關聯視窗(NULL 為執行緒計時器)
    UINT_PTR nIDEvent,   // 計時器 ID(自訂,非 0)
    UINT uElapse,        // 間隔毫秒(系統最小約 10-15ms)
    TIMERPROC lpTimerFunc // 回呼函式(NULL 表示用 WM_TIMER 訊息)
);

BOOL KillTimer(HWND hWnd, UINT_PTR uIDEvent);  // 必須配對 ID 銷毀

兩種通知模式比較

特性lpTimerFunc == NULL (WM_TIMER)lpTimerFunc != NULL (回呼)
處理位置視窗程序 WndProc獨立回呼函式(系統執行緒池)
優先級低(訊息佇列中最後處理)較高(直接由系統呼叫)
精確度受訊息迴圈擁塞影響相對精確,但非即時
適用場景UI 更新、動畫、輪詢非 UI 邏輯、資料採樣
參數傳遞透過 wParam 取得 ID參數直接傳遞

WM_TIMER 低優先級實證

  • 系統先處理輸入、繪圖、掛起等高優先級訊息。
  • 訊息佇列中無其他訊息時,才派發 WM_TIMER。
  • 若主執行緒忙碌(長時間計算、阻塞 I/O),計時器訊息會**堆疊合併**(多個間隔合併為單一 WM_TIMER)。
  • 不適合高精度計時,需用 QueryPerformanceCounter、CreateTimerQueueTimer 或多媒體計時器 timeSetEvent。

閃爍視窗完整範例

回呼函式模式

BOOL isRed = FALSE;

VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
    isRed = !isRed;  // 切換狀態
    RECT rc;
    GetClientRect(hwnd, &rc);
    InvalidateRect(hwnd, &rc, TRUE);  // 觸發 WM_PAINT
}

// WndProc 中
case WM_CREATE:
    SetTimer(hWnd, 1, 1000, TimerProc);  // 1秒間隔,使用回呼
    return 0;

case WM_PAINT: {
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hWnd, &ps);
    RECT rc;
    GetClientRect(hWnd, &rc);
    if (isRed) {
        HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));
        FillRect(hdc, &rc, brush);
        DeleteObject(brush);
    }
    EndPaint(hWnd, &ps);
    return 0;
}

case WM_DESTROY:
    KillTimer(hWnd, 1);  // 必須清理
    PostQuitMessage(0);
    return 0;

WM_TIMER 訊息模式


case WM_CREATE:
    SetTimer(hWnd, 1, 1000, NULL);  // 無回呼,用 WM_TIMER
    return 0;

case WM_TIMER:
    if (wParam == 1) {
        isRed = !isRed;
        InvalidateRect(hWnd, NULL, TRUE);
    }
    return 0;

執行效果

視窗客戶區每秒在紅色填充與背景色之間切換。

進階計時器選擇指南

需求推薦方案精度
UI 動畫、週期性更新SetTimer (WM_TIMER)~15ms
背景工作排程SetTimer (回呼) / CreateTimerQueueTimer~1ms
高精度測量、多媒體同步timeSetEvent / QueryPerformanceCounter 迴圈~1ms / 奈秒級
系統級排程、跨進程任務排程器 / Waitable Timer秒級

常見錯誤

  1. 忘記 KillTimer 導致資源洩漏、視窗銷毀後仍觸發回呼。
  2. 重複 SetTimer 相同 ID 會**替換**舊計時器(間隔、模式皆更新)。
  3. 在 WM_TIMER 執行耗時操作阻塞 UI 執行緒 → 改用回呼或背景執行緒。
  4. 假設計時器精確觸發 → 必須設計容忍抖動的邏輯。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved