首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Win32 WM_TIMER 斷點無法命中:消息泵與定時器優先級問題分析

     編輯:程式設計綜合問答

現象

設置 SetTimer(hwnd, 1, 100, NULL),在 WM_TIMER case 下打斷點,調試器從未命中。

可能原因

  1. 消息泵阻塞:主線程執行耗時操作導致 GetMessage/DispatchMessage 循環卡住,定時器消息無法分發。
  2. 定時器精度:100ms 間隔較短,若處理超過 100ms 會導致消息丟失或合併。
  3. 調試器干擾:斷點命中時系統暫停,定時器繼續觸發,單步執行可能導致消息隊列堆積。

標準修正範例

#include <windows.h>
#define ID_TIMER 1

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
        case WM_CREATE:
            SetTimer(hwnd, ID_TIMER, 1000, NULL); // 建議 1s 觀察
            return 0;
        case WM_TIMER:
            // 僅做輕量操作,如 InvalidateRect 觸發重繪
            InvalidateRect(hwnd, NULL, FALSE);
            return 0;
        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            SYSTEMTIME st; GetLocalTime(&st);
            TCHAR buf[64];
            wsprintf(buf, TEXT("%02d:%02d:%02d"), st.wHour, st.wMinute, st.wSecond);
            TextOut(hdc, 10, 10, buf, lstrlen(buf));
            EndPaint(hwnd, &ps);
            return 0;
        }
        case WM_DESTROY:
            KillTimer(hwnd, ID_TIMER);
            PostQuitMessage(0);
            return 0;
    }
    return DefWindowProc(hwnd, msg, wp, lp);
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow) {
    WNDCLASS wc = {CS_HREDRAW|CS_VREDRAW, WndProc, 0,0, hInst,
        LoadIcon(NULL,IDI_APPLICATION), LoadCursor(NULL,IDC_ARROW),
        (HBRUSH)(COLOR_WINDOW+1), NULL, TEXT("TimerDemo")};
    RegisterClass(&wc);
    HWND hwnd = CreateWindow(TEXT("TimerDemo"), TEXT("Timer"), WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, hInst, NULL);
    ShowWindow(hwnd, nCmdShow);
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

調試建議

  • 將間隔改為 1000ms 降低頻率。
  • 在 WM_TIMER 僅設置標誌位或 InvalidateRect,耗時操作放入工作線程。
  • 使用 OutputDebugString 替代斷點輸出調試信息,避免調試器干擾消息泵。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved