SetTimer与CWnd :: SetTimer

时间:2018-06-24 14:13:10

标签: 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, nElapse,
        lpfnTimer); }

但是SetTimerCWnd::SetTimer文档并不相同。

1。 nIDEvent参数

  

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

     

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

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

2。返回值

  

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

     

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

SetTimer不会生成新的计时器ID,也不返回计时器ID,因此请使用KillTimer参数调用nIDEvent。但是CWnd::SetTimer在某些情况下会生成新的计时器ID,因此请使用返回的值调用KillTimer

那么,哪个文件是正确的?


我想使用WinAPI SetTimer进行回调,并且可以在我的PC上使用。但是,如果某些平台不替换现有计时器,那么我将无法接受回调计时器。

1 个答案:

答案 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,并且仍然会收到两个事件。