關於SetTimer函數的總結

關於SetTimer函數的總結

在使用 SOUI 編寫Windows程序時,似乎曾經看到過 SOUI 中限制了 SetTimer 函數能啓動的定時器的個數,於是今天就去 MSDN 看了下Windows本身是否也限制了單個程序能啓動的定時器個數,於是就有了這篇總結。

先下結論好了:微軟在 MSDN 上並沒有寫明單個程序能啓動的定時器的個數。

但是,還是學到了不少關於使用 SetTimer 函數時之前所不知道的地方,下面就來說一說。

慣例,先上 MSDN 關於 SetTimer 函數的原型。

UINT_PTR SetTimer(
  HWND      hWnd,
  UINT_PTR  nIDEvent,
  UINT      uElapse,
  TIMERPROC lpTimerFunc
);

那麼在使用 SetTimer 函數時需要注意的地方是什麼呢。

MSDN 中關於 nIDEvent 參數有這樣的說明:
A nonzero timer identifier. If the hWnd parameter is NULL, and the nIDEvent does not match an existing timer then it is ignored and a new timer ID is generated. 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. Therefore, a message will be sent after the current time-out value elapses, but the previously set time-out value is ignored. If the call is not intended to replace an existing timer, nIDEvent should be 0 if the hWnd is NULL

上面這段話說了三點:

  1. SetTimer函數的第一個參數傳遞NULL時,SetTimer函數會忽略第二個參數,轉而啓動一個隨機的定時器並返回它的數值,當調用KillTimer函數時需要使用該數值,而不是調用SetTimer函數時傳遞的數值。
  2. SetTimer函數的第二個參數的數值是當前計時中的定時器的數值時,系統會將那個定時器重置,重新計時,計時數值爲最新設置的 uElapse 數值。
  3. 關於 nIDEvent 的大小沒有限制。

也就是說,當 hWndNULL 時,無論第二個參數傳遞的是什麼數值(傳遞 NULL也行),系統啓動的都不是你所指定的那個定時器,所以需要自己手動保存好 SetTimer 函數返回的數值,留待以後調用 KillTimer 函數時使用。

而且還要說一點:當 hWndNULL 時,調用線程還是會收到 WM_TIMER 消息的,但是 GetMessagePeekMesage 獲取到的 MSG 數據中的 hWndNULL(跟 PostThreadMessage 同理)。所以默認情況下,在MFC中使用 SetTimer(NULL, uElapse, NULL)::SetTimer(NULL, NULL, uElapse, NULL) 時,在 OnTimer 函數中都是無法響應該定時器的,需要重寫MFC的 PreTranslateMessage 函數才能響應該定時器。

關於 lpTimerFunc 參數,MSDN 的說法也值得注意:
An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER.

就是說:當 lpTimerFunc 不爲NULL時,窗口過程響應WM_TIMER時會執行該函數,並不會執行默認的窗口過程。

所以,在MFC中,如果不想重寫MFC的 PreTranslateMessage 函數的話,可以設定 lpTimerFunc 參數,這樣也能處理 hWndNULLSetTimer函數了。

好了,上面就是本人在 MSDN 看到的關於 SetTimer 函數的一點總結了。本人限於能力,上文中難免有錯誤的地方,若讀者發現上文的錯誤,請於評論區中指出,本人看到之後會立即修改的,謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章