背景
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文件不一样。
1.
nIDEvent
范围
SetTimer
:
If the hWnd parameter is not NULL and the window specified by hWnd already has a timer with the value nIDEvent, then the existing timer is replaced by the new timer. When SetTimer replaces a timer, the timer is reset.
CWnd::SetTimer
:
Specifies a nonzero timer identifier. If the timer identifier is unique, this same value is returned bySetTimer
. Otherwise,SetTimer
determines a new unique value and returns that. For a window timer (which has a NULL callback function), the value must be unique only for other windows timers that are associated with the current window. For a callback timer, the value must be unique for all timers in all processes. Therefore, when you create a callback timer, it is more likely that the returned value might differ from the value you specify.
SetTimer
不依赖于回调参数,总是替换现有的计时器。但是CWnd::SetTimer
取决于回调参数,如果指定了回调,可能会生成一个新的定时器 ID,因为 对于所有进程中的所有计时器,该值必须是唯一的 .2. 返回值
SetTimer
:
If the function succeeds and the hWnd parameter is not NULL, then the return value is a nonzero integer. An application can pass the value of the nIDEvent parameter to the KillTimer function to destroy the timer.
CWnd::SetTimer
:
The timer identifier of the new timer if the function is successful. This value may or may not be equal to the value passed in through thenIDEvent
parameter. An application should always pass the return value to the KillTimer member function to kill the timer.
SetTimer
不生成新的定时器 id 并且不返回定时器 id,因此调用 KillTimer
与 nIDEvent
范围。但是CWnd::SetTimer
在某些情况下会生成新的计时器 ID,因此请调用 KillTimer
与返回值。因此,哪个文件是正确的?
我想使用 WinAPI
SetTimer
带有回调,它适用于我的电脑。但是如果某些平台不替换现有的计时器,我无法接受回调计时器。
最佳答案
据我所知,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 两次,并且仍然接收两个事件。
关于winapi - SetTimer 与 CWnd::SetTimer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51010727/