在MFC中,我试图设置一个空处理程序计时器(即没有窗口).但是我无法在CWinApp MESSAGE_MAP中处理WM_TIMER事件.这可能吗?如果是这样,怎么样?
正如MSDN所述,有两种操作模式SetTimer()
:一种将定时器与窗口相关联,另一种将定时器与线程的消息队列相关联.当你有一个窗口,你可以使用前者; 否则,你必须使用后者.而CWinApp
不是一个窗口.
UINT_PTR uTimerId = SetTimer(NULL, 0, 2000, NULL); TRACE(_T("Timer created - ID=%x\n"), uTimerId);
这将创建一个新的计时器,设置为每两秒触发一次,仅与当前线程的消息队列相关联.当你没有将它与一个窗口关联时,你不能指定一个计时器ID,所以保存在一个类成员或其他东西中返回的ID - 如果你忘记了,你将有一个大概的时间杀死计时器.然后,您可以在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);
这与第一个示例几乎完全相同:新的计时器配置为每两秒触发一次,与当前线程的消息队列相关联......但是这个计时器有一个与之关联的回调地址.并且默认消息处理程序知道在处理这样的定时器消息时调用回调,因此您不必费心连接到消息循环.
你去吧 两种使用计时器的方法CWinApp
.