Win32程序中SetTimer设置的定时器回调函数未被调用的原因排查
Win32程序中SetTimer设置的定时器回调函数未被调用的原因排查
看起来你遇到的问题是定时器回调完全没触发,窗口能正常创建但就是看不到MessageBox。我帮你看了代码,问题出在WM_PAINT消息的错误处理上,咱们一步步说清楚:
为什么WM_PAINT会影响定时器?
WM_PAINT是Win32里的特殊消息,它属于“悬而未决”的消息——只要窗口的客户区有需要重绘的区域,系统就会把WM_PAINT放到消息队列里。如果你的程序没有正确处理它(也就是没调用BeginPaint和EndPaint),系统会认为这个消息还没被处理,会持续往队列里塞WM_PAINT消息。这样你的消息循环就会一直忙着处理WM_PAINT,根本没机会处理定时器的WM_TIMER消息(WM_TIMER的优先级比WM_PAINT低,而且只有当消息队列空的时候才会触发)。你的代码哪里错了?
看你的窗口过程里的WM_PAINT分支:case WM_PAINT: return 0;直接
return 0等于完全没处理这个消息,系统会一直认为窗口需要重绘,WM_PAINT消息会源源不断地进来,把消息队列堵死了。怎么修复?
正确处理WM_PAINT,必须调用BeginPaint和EndPaint来告诉系统“我已经处理完重绘了”,哪怕你什么都不想画:case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // 这里可以留空,或者添加你需要的绘制逻辑 EndPaint(hwnd, &ps); } return 0;额外的小建议:
- 可以检查一下
SetTimer的返回值,如果返回0说明定时器创建失败,方便排查其他问题:if (!SetTimer(hwnd, 1, 100, timer_proc)) { MessageBoxA(hwnd, "SetTimer failed!", "Error", MB_ICONERROR); } - 另外,WM_SIZE分支直接
return 0其实没问题,但如果以后需要处理窗口大小变化,记得按需添加逻辑,不过这个不是当前问题的原因。
- 可以检查一下
修改完WM_PAINT的处理后,你再编译运行,定时器应该就能正常触发了,每隔100ms会弹出一个MessageBox。
备注:内容来源于stack exchange,提问作者Limina102
相关产品推荐
相关产品推荐

