前面一節雞啄米講了CTime類(lèi)和CTimeSpan類(lèi)的使用,本節繼續講與時(shí)間有關(guān)的定時(shí)器。定時(shí)器并不是一個(gè)類(lèi),主要考慮到,提起時(shí)間的話(huà)就不能不說(shuō)定時(shí)器,所以就把它放到CTime和CTimeSpan之后講解。
定時(shí)器簡(jiǎn)介
定時(shí)器,可以幫助開(kāi)發(fā)者或者用戶(hù)定時(shí)完成某項任務(wù)。在使用定時(shí)器時(shí),我們可以給系統傳入一個(gè)時(shí)間間隔數據,然后系統就會(huì )在每個(gè)此時(shí)間間隔后觸發(fā)定時(shí)處理程序,實(shí)現周期性的自動(dòng)操作。例如,我們可以在數據采集系統中,為定時(shí)器設置定時(shí)采集時(shí)間間隔為1個(gè)小時(shí),那么每隔1個(gè)小時(shí)系統就會(huì )采集一次數據,這樣就可以在無(wú)人操作的情況下準確的進(jìn)行操作。
MFC定時(shí)器
VS2010編程中,我們可以使用MFC的CWnd類(lèi)提供的成員函數SetTimer實(shí)現定時(shí)器功能,也可以使用Windows API函數SetTimer來(lái)實(shí)現。兩者使用方法實(shí)際上很類(lèi)似,但也有不同。
CWnd類(lèi)的SetTimer成員函數只能在CWnd類(lèi)或其派生類(lèi)中調用,而API函數SetTimer則沒(méi)有這個(gè)限制,這是一個(gè)很重要的區別。因為本教程主要是講解MFC編程,所以這里就先重點(diǎn)講解MFC定時(shí)器的用法,關(guān)于A(yíng)PI函數SetTimer的用法雞啄米會(huì )在MFC定時(shí)器講解的基礎上進(jìn)行延伸。
雞啄米下面分步驟給出使用MFC定時(shí)器的方法。
1、啟動(dòng)定時(shí)器。
啟動(dòng)定時(shí)器就需要使用CWnd類(lèi)的成員函數SetTimer。CWnd::SetTimer的原型如下:
UINT_PTR SetTimer(
UINT_PTR nIDEvent,
UINT nElapse,
void (CALLBACK* lpfnTimer
)(HWND,
UINT,
UINT_PTR,
DWORD
)
);
參數nIDEvent指定一個(gè)非零的定時(shí)器ID;參數nElapse指定間隔時(shí)間,單位為毫秒;參數lpfnTimer指定一個(gè)回調函數的地址,如果該參數為NULL,則WM_TIMER消息被發(fā)送到應用程序的消息隊列,并被CWnd對象處理。如果此函數成功則返回一個(gè)新的定時(shí)器的ID,我們可以使用此ID通過(guò)KillTimer成員函數來(lái)銷(xiāo)毀該定時(shí)器,如果函數失敗則返回0。
通過(guò)SetTimer成員函數我們可以看出,處理定時(shí)事件可以有兩種方式,一種是通過(guò)WM_TIMER消息的消息響應函數,一種是通過(guò)回調函數。
如果要啟動(dòng)多個(gè)定時(shí)器就多次調用SetTimer成員函數。另外,在不同的CWnd中可以有ID相同的定時(shí)器,并不沖突。
2、為WM_TIMER消息添加消息處理函數,或者定義回調函數。
如果調用CWnd::SetTimer函數時(shí)最后一個(gè)參數為NULL,則通過(guò)WM_TIMER的消息處理函數來(lái)處理定時(shí)事件。添加WM_TIMER消息的處理函數的方法是,在VS2010工程的Class View類(lèi)視圖中找到要添加定時(shí)器的類(lèi),點(diǎn)擊右鍵,選擇Properties,顯示其屬性頁(yè),然后在屬性頁(yè)工具欄上點(diǎn)擊Messages按鈕,下面列表就列出了所有消息,找到WM_TIMER消息,添加消息處理函數。添加后,cpp文件中會(huì )出現類(lèi)似如下內容:
之后就可以在OnTimer函數中進(jìn)行相應的處理了。OnTimer的參數nIDEvent為定時(shí)器ID,即在SetTimer成員函數中指定的定時(shí)器ID,如果有多個(gè)定時(shí)器,我們可以像下面這樣處理:
如果調用CWnd::SetTimer函數時(shí)最后一個(gè)參數不為NULL,則需要定義回調函數?;卣{函數的形式如下:
參數hWnd為調用SetTimer成員函數的CWnd對象的句柄,即擁有此定時(shí)器的窗口的句柄;參數nMsg為WM_TIMER,而且總是為WM_TIMER;參數nIDEvent為定時(shí)器ID;參數dwTime為系統啟動(dòng)以來(lái)的毫秒數,即GetTickCount函數的返回值。
這樣CWnd::SetTimer函數最后一個(gè)參數就可以為T(mén)imerProc。
這里注意下,回調函數的名稱(chēng)不一定為T(mén)imerProc,可以取其他名字,但返回值類(lèi)型、參數的類(lèi)型和個(gè)數不能改變。
雞啄米給出一個(gè)回調函數的例子:
回調函數為全局函數,需要寫(xiě)在使用它的位置的前面,或者寫(xiě)在后面然后在使用之前聲明。
3、銷(xiāo)毀定時(shí)器。
不再使用定時(shí)器時(shí),可以銷(xiāo)毀它。銷(xiāo)毀定時(shí)器需使用CWnd類(lèi)的KillTimer成員函數,CWnd::KillTimer函數的原型如下:
參數nIDEvent為要銷(xiāo)毀的定時(shí)器的ID,是調用CWnd::SetTimer函數時(shí)設置的定時(shí)器ID。如果定時(shí)器被銷(xiāo)毀則返回TRUE,而如果沒(méi)有找到指定的定時(shí)器則返回FALSE。
如果要銷(xiāo)毀多個(gè)定時(shí)器,則多次調用KillTimer函數并分別傳入要銷(xiāo)毀的定時(shí)器的ID。
通過(guò)Windows API函數使用定時(shí)器
如果我們不使用MFC定時(shí)器,而通過(guò)Windows API函數使用定時(shí)器,其實(shí)是很類(lèi)似的。下面雞啄米簡(jiǎn)單說(shuō)下步驟吧。
1、啟動(dòng)定時(shí)器。
使用API函數SetTimer啟動(dòng)定時(shí)器,SetTimer函數的原型如下:
參數hWnd為與定時(shí)器關(guān)聯(lián)的窗口的句柄;參數nIDEvent為非零的定時(shí)器ID,如果hWnd等于NULL,且還不存在ID為nIDEvent的定時(shí)器,那么nIDEvent參數被忽略,然后生成一個(gè)新ID的定時(shí)器,而如果hWnd不為NULL,且hWnd指定的窗口已存在ID為nIDEvent的定時(shí)器,那么這個(gè)已存在的定時(shí)器被新定時(shí)器所取代。參數uElapse和lpTimerFunc同CWnd::SetTimer函數。
2、為WM_TIMER消息添加消息處理函數,或者定義回調函數。
如果調用SetTimer函數時(shí)最后一個(gè)參數為NULL,我們需要自己為WM_TIMER消息添加處理函數,要注意的是,WM_TIMER消息的附加數據wParam為定時(shí)器ID,lParam為回調函數的指針,如果調用SetTimer時(shí)回調函數為NULL,那么lParam也為NULL。
而如果調用SetTimer函數時(shí)最后一個(gè)參數不為NULL,我們就需要定義回調函數?;卣{函數的定義同MFC定時(shí)器。
3、銷(xiāo)毀定時(shí)器。
銷(xiāo)毀定時(shí)器使用KillTimer API函數,原型如下:
參數hWnd為與定時(shí)器關(guān)聯(lián)的窗口的句柄,與啟動(dòng)定時(shí)器時(shí)SetTimer函數的hWnd參數值相同;參數uIDEvent為要銷(xiāo)毀的定時(shí)器的ID,如果傳遞給SetTimer的參數hWnd有效,則uIDEvent應與傳遞給SetTimer的參數nIDEvent相同,而如果SetTimer的參數hWnd為NULL,則uIDEvent應為SetTimer返回的定時(shí)器ID。該函數成功則返回TRUE,否則返回FALSE。
MFC定時(shí)器應用實(shí)例
雞啄米給大家演示一個(gè)定時(shí)器的例子,該實(shí)例功能很簡(jiǎn)單,就是使用兩個(gè)定時(shí)器,定時(shí)更新兩個(gè)編輯框中的顯示內容,第一個(gè)編輯框每秒刷新一次,從1刷新到10,然后銷(xiāo)毀定時(shí)器,第二個(gè)編輯框每?jì)擅胨⑿乱淮?,?刷新到5,然后銷(xiāo)毀定時(shí)器。下面簡(jiǎn)單說(shuō)下步驟:
1、創(chuàng )建基于對話(huà)框的工程,名稱(chēng)設為“Example44”。
2、在自動(dòng)生成的對話(huà)框模板IDD_EXAMPLE44_DIALOG中,刪除“TODO: Place dialog controls here.”靜態(tài)文本控件。添加兩個(gè)靜態(tài)文本框控件,Caption分別設為“1秒鐘刷新一次”和“2秒鐘刷新一次”,再添加兩個(gè)個(gè)Edit Control控件,ID使用默認的IDC_EDIT1和IDC_EDIT2,兩者的Read Only屬性都設為T(mén)rue。此時(shí)的對話(huà)框模板如下圖:

3、為CExample44Dlg類(lèi)添加兩個(gè)成員變量,分別為m_nData1、m_nData2,并在CExample44Dlg類(lèi)的構造函數中初始化:
4、在對話(huà)框模板上雙擊OK按鈕,添加點(diǎn)擊消息的處理函數,并修改如下:
這樣,點(diǎn)擊OK按鈕時(shí)就不會(huì )退出,而是啟動(dòng)兩個(gè)定時(shí)器。
5、根據上面MFC定時(shí)器講解中為WM_TIMER消息添加處理函數的方法,添加WM_TIMER的消息處理函數OnTimer,并修改其實(shí)現如下:
6、運行程序,點(diǎn)擊OK按鈕,查看效果。

關(guān)于定時(shí)器的內容就講這些,相信了解了這些,一般的定時(shí)器應用都能解決了。雞啄米謝謝大家一直以來(lái)的陪伴,讓我有動(dòng)力更新下去??!
聯(lián)系客服