Winapi SetTimer vs CWnd::SetTimer 背景

Winapi SetTimer vs CWnd::SetTimer 背景,winapi,mfc,Winapi,Mfc,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, nElaps

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); }
但是,文件和文件是不一样的

1. <代码>NIDDevent参数
SetTimer

如果hWnd参数不是NULL,并且hWnd指定的窗口已经有一个值为nIDEvent的计时器,则现有计时器将替换为新计时器。当设置计时器替换计时器时,计时器将重置

CWnd::SetTimer

指定非零计时器标识符。如果计时器标识符是唯一的,则相同的值由
SetTimer
返回。否则,
SetTimer
将确定一个新的唯一值并返回该值。对于窗口计时器(具有空回调函数),该值必须仅对与当前窗口关联的其他窗口计时器唯一。对于回调计时器,该值对于所有进程中的所有计时器都必须是唯一的。因此,在创建回调计时器时,返回的值很可能与指定的值不同

SetTimer
不依赖于回调参数,始终替换现有计时器。但是
CWnd::SetTimer
取决于回调参数,如果指定了回调,则可能会生成新的计时器ID,因为该值对于所有进程中的所有计时器都必须是唯一的

2.返回值
SetTimer

如果函数成功且hWnd参数不是NULL,则返回值为非零整数。应用程序可以将nIDEvent参数的值传递给KillTimer函数以销毁计时器

CWnd::SetTimer

如果功能成功,则新计时器的计时器标识符。该值可能等于也可能不等于通过
nIDEvent
参数传入的值。应用程序应始终将返回值传递给KillTimer成员函数以终止计时器

SetTimer
不会生成新的计时器id,也不会返回计时器id,因此使用
nIDEvent
参数调用
KillTimer
。但是在某些情况下,
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调试器跟踪):

上一次SetTimer调用使用了不同的窗口,该窗口两次给出相同的事件。但每次,返回值都与为计时器传递的值相同。相同的值用于nIDEvent

CWnd文档要么已经过时,要么表现得非常谨慎——我们知道返回值是ID,所以应该始终使用它

然而,有一种说法显然是错误的:

对于回调计时器,该值对于所有进程中的所有计时器都必须是唯一的


我刚刚演示了我可以在同一个进程中使用同一ID两次,并且仍然可以接收这两个事件。

我依赖于
SetTimer()
的记录行为,它似乎可以像广告中那样工作。如果你真的想知道,你应该运行一些简单的测试。当MFC和WinAPI文档之间存在差异时,我通常依赖后者。毕竟,它是信息的主要来源,尤其是在MFC只是转发给API的情况下。据我所知,MFC文档在编写时是正确的,但API发生了变化,MFC从未更新以匹配。MFC是否可以追溯到16位Windows?在现代世界中,“所有进程”的限制都没有多大意义。@ MarkRansom,是的:MFC是在1992引入的,微软的C/C++ 7编译器用于Windows 16位版本,作为面向Windows API(维基百科)的极其薄的面向对象的C++封装器。
timerID=2
timerID=2
timerID=4
timerID=4
nIDEvent=2, hWnd=0x00000000002d0bb8
nIDEvent=4, hWnd=0x00000000002d0bb8
nIDEvent=4, hWnd=0x0000000000140bd0