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