如何使用 MFC 在 CWinApp 中接收计时器事件?
Posted
技术标签:
【中文标题】如何使用 MFC 在 CWinApp 中接收计时器事件?【英文标题】:How to receive timer events in CWinApp with MFC? 【发布时间】:2008-10-17 17:43:01 【问题描述】:在 MFC 中,我试图设置一个空处理程序计时器(即没有窗口)。但我无法处理 CWinApp MESSAGE_MAP 中的 WM_TIMER 事件。这可能吗?如果有,怎么做?
【问题讨论】:
【参考方案1】:正如 MSDN 所说,SetTimer()
有两种操作模式:一种将定时器与窗口相关联,另一种将定时器与线程的消息队列相关联。当你有一个窗口时,你可以使用前者;否则,您必须使用后者。 CWinApp
不是一个窗口。
在线程队列中捕获定时器消息
UINT_PTR uTimerId = SetTimer(NULL, 0, 2000, NULL);
TRACE(_T("Timer created - ID=%x\n"), uTimerId);
这将创建一个新的计时器,设置为每两秒触发一次,仅与当前线程的消息队列相关联。当您不将计时器 ID 与窗口关联时,您无法指定计时器 ID,因此请将返回的 ID 保存在类成员或其他东西中 - you'll have a rough time killing the timer later on if you forget。然后,您可以在 CWinApp::PreTranslateMessage()
覆盖中处理它:
BOOL CMyFunkyApp::PreTranslateMessage(MSG* pMsg)
if (pMsg->message == WM_TIMER)
TRACE(_T("Timer fired - ID=%x\n"), pMsg->wParam);
return CWinApp::PreTranslateMessage(pMsg);
请注意,像这样连接到线程的消息循环是处理以这种方式设置的计时器的唯一方法 - 正如我们所讨论的,没有窗口,尽管 MFC 确实提供了消息映射工具对于CWinApp
,您不能使用ON_WM_*()
宏,因为...好吧,因为它不是一个窗口。但是,还有另一种稍微不太麻烦的方法:回调。
使用回调处理定时器消息
void CALLBACK TimerCallback(HWND, UINT, UINT_PTR id, DWORD dwTime)
TRACE(_T("Timer fired - ID=%x\n"), id);
//...
UINT_PTR uTimerId = SetTimer(NULL, 0, 2000, &TimerCallback);
TRACE(_T("Timer created - ID=%x\n"), uTimerId);
这与第一个示例几乎完全相同做同样的事情:一个新的计时器被配置为每两秒触发一次,与当前线程的消息队列相关...但是 这个 em> 有一个与之关联的回调地址。并且默认消息处理程序知道在处理此类计时器消息时调用回调,因此您不必费心挂钩到消息循环中。
所以你去。来自CWinApp
的两种定时器使用方法。
【讨论】:
【参考方案2】:我通过制作一个不可见的窗口并在其上设置计时器来做到这一点。
【讨论】:
【参考方案3】:查看 Raymond Chen 的这篇文章。有一些有趣的掘金可以说明你的工作可能会让你摆脱麻烦。
Why your thread is spending all its time processing meaningless thread timers
【讨论】:
以上是关于如何使用 MFC 在 CWinApp 中接收计时器事件?的主要内容,如果未能解决你的问题,请参考以下文章
猎豹MFC1 第一个窗口CWinApp CFrameWnd InitInstance 消息映射CPaint CRect Create