很久之前就想給Vckbase寫點什麼東西了,畢業至今,在vckbase中學了不少東西,也拿了不少代碼,今天決定要回報一下,不管老婆呆會會不會擰我耳朵了。
毫秒定時器,為什麼要使用毫秒定時器呢?我想原因有兩個。第一:CWnd裡面的timer不能精確到毫秒級,所以必須要寫一個精確到毫秒級的。第二:用CWnd裡面的timer代價太大,因為有時我們的類根本就沒有窗口,為了使用timer,而不得不從CWnd裡派生。本人寫的這個mmtimer,主要是為了解決上面這兩點而設計的。
再加上,這段時間看了一下設計模式,所以基本上這些代碼是我這幾個月來設計模式的總結,如果寫得不好,敬請各位大蝦指教。
運行結果如下:
圖一 毫秒定時器
好了我們先來看看實現毫秒定時器的關鍵技術吧。其實異常的簡單,主要用到如下幾個函數,(見代碼中CMMTimers)
1) timeGetDevCaps,得到當前計算機的時間精度。
2) timeBeginPeriod,設定當前定時器的精確度。例如設定為5,表示誤差不會大於5毫秒。
3) timeEndPeriod. 跟2相對應,結束了定時精度.
(其實我的這些代碼中有沒有這三個函數,效果也是一樣的)
4) timeSetEvent(...pfn...).開始定時,該函數中,有一個參數時回調函數指針,以及回調函數的參數,我的代碼中是internalTimerProc,
和m_Recoder[MMRecoder::nRes](該參數指明定時器ID,一個CMMTimers的指針)
5)timeKillEvent.終止定時器。
如果對上述函數不理解也沒關系,我已經把它們封裝成一個類了,對了就叫CMMTimers.
為了使你不必去理解上述這些函數,我作出封裝,CMMTimers主要有如下幾個函數接口:
1)bool stopTimer(int nTimerID) 作用跟KillTimer(int nTimerID) 一樣.
2)bool startTimer(UINT period,CTimerListener *pListener = NULL,int nTimerID = 1,bool oneShot = FALSE);相當於SetTimer(int nTimerID).
nTimerID,就是定時器ID,oneShot就是是否只運行一次,你可能會說CTimerListener是個什麼東西,這個下面我再解釋。
3)stopTimer(),關閉所有定時器。
4)timerProc()定時響應函數。相當於OnTimer.
說到這裡的時候,其實我們現在就可以用這個類了,只不如果我不說CTimerListener是個什麼東西,你始終會覺得納悶。好吧,讓我畫個UML圖好了。
圖二 毫秒定時器 UML圖
有了UML圖之後,知道CTimerListener是個抽象接口了吧,什麼?UML圖看不懂?回去看書去,俺可沒這個義務教你看UML圖呀。
來到這裡你就已經知道,只要CtestMMTimerDlg調用StartTimer(),StopTimer(),以及重載OnMMTimer()就OK了,其用法與SetTimer,KillTimer,OnTimer是一樣的。
這裡CtestMMTimerDlg,的基類是CDialog,而CDialog的基類是CWnd純屬巧合,它其實可以是任何的類,如CStudent,等完全沒有窗口的類。
自己看代碼吧。如果覺得有何不妥之處請與我聯系。
結束語:又一次,老婆在等我完成工作中睡著了.....當程序員的老婆,有時真是慘。