MFC的CWnd::SetTimer
简单地调用WinAPI的SetTimer
。
_AFXWIN_INLINE UINT_PTR CWnd::SetTimer(UINT_PTR nIDEvent, UINT nElapse,
void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD))
{ ASSERT(::IsWindow(m_hWnd)); return ::SetTimer(m_hWnd, nIDEvent, nElapse,
lpfnTimer); }
但是SetTimer和CWnd::SetTimer文档并不相同。
nIDEvent
参数
SetTimer
:
如果 hWnd 参数不是 NULL ,并且 hWnd 指定的窗口已经具有值为 nIDEvent 的计时器,然后将现有计时器替换为新计时器。当 SetTimer 替换计时器时,计时器将重置。
CWnd::SetTimer
:
指定非零计时器标识符。如果计时器标识符是唯一的,则SetTimer
返回相同的值。否则,SetTimer
确定一个新的唯一值并返回。对于窗口计时器(具有NULL回调函数),该值仅对于与当前窗口关联的其他窗口计时器必须唯一。对于回调计时器,该值对于所有进程中的所有计时器都必须是唯一的。因此,在创建回调计时器时,返回的值很可能与您指定的值不同。
SetTimer
不依赖于回调参数,并且始终替换现有的计时器。但是CWnd::SetTimer
取决于回调参数,如果指定了回调,则可能会生成新的计时器ID,因为该值对于所有进程中的所有计时器都必须是唯一的。
SetTimer
:
如果函数成功且 hWnd 参数不是 NULL ,则返回值为非零整数。应用程序可以将 nIDEvent 参数的值传递给 KillTimer 函数,以销毁计时器。
CWnd::SetTimer
:
如果功能成功,则新计时器的计时器标识符。此值可以等于或可以不等于通过nIDEvent
参数传递的值。应用程序应始终将返回值传递给KillTimer成员函数以终止计时器。
SetTimer
不会生成新的计时器ID,也不返回计时器ID,因此请使用KillTimer
参数调用nIDEvent
。但是CWnd::SetTimer
在某些情况下会生成新的计时器ID,因此请使用返回的值调用KillTimer
。
那么,哪个文件是正确的?
我想使用WinAPI SetTimer
进行回调,并且可以在我的PC上使用。但是,如果某些平台不替换现有计时器,那么我将无法接受回调计时器。
答案 0 :(得分:1)
MFC文档不正确。我已经进行了广泛的测试,并且只要窗口是相同的,计时器始终会替换以前的计时器。无论有没有回调,都是如此。
通过回调,我运行了以下测试:
static void CALLBACK MyTimerProc(HWND hWnd, UINT nMsg, UINT_PTR nIDEvent, DWORD dwTime) {
KillTimer(hWnd, nIDEvent);
}
...
timerID = SetTimer(2, 1000, MyTimerProc);
timerID = SetTimer(2, 1100, MyTimerProc);
timerID = SetTimer(4, 1200, MyTimerProc);
timerID = GetParentFrame()->SetTimer(4, 1300, MyTimerProc);
结果是(来自VS调试器跟踪):
timerID=2
timerID=2
timerID=4
timerID=4
nIDEvent=2, hWnd=0x00000000002d0bb8
nIDEvent=4, hWnd=0x00000000002d0bb8
nIDEvent=4, hWnd=0x0000000000140bd0
最后一次SetTimer调用使用了一个不同的窗口,该窗口两次给同一个事件。但是每次,返回值都等于为计时器传递的值。并将相同的值用于nIDEvent。
CWnd文档要么已过时,要么出于极端谨慎的考虑-我们知道返回值是ID,因此我们应该始终使用该ID。
但是,有一种说法显然是错误的:
对于回调计时器,该值对于所有进程中的所有计时器都必须是唯一的
我只是演示了我可以在相同流程中使用两次相同的ID,并且仍然会收到两个事件。