UINT_PTR SetTimer( HWND hWnd, // 窗口句柄 UINT_PTR nIDEvent, // 定時器ID,多個定時器時,可以通過該ID判斷是哪個定時器 UINT uElapse, // 時間間隔,單位為毫秒 TIMERPROC lpTimerFunc // 回調函數 );
void CTimerTestDlg::OnTimer(UINT nIDEvent) { switch (nIDEvent) { case 24: ///處理ID為24的定時器 Draw1(); break; case 25: ///處理ID為25的定時器 Draw2(); break; } CDialog::OnTimer(nIDEvent); }
void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime) { switch(nTimerid) { case 1: ///處理ID為1的定時器 Do1(); break; case 2: ///處理ID為2的定時器 Do2(); break; } }
如:KillTimer(1);
——————————————————————————————————————————————————
MFC中定時器的使用
巧妙地使用定時器能達到意想不到的效果,寫界面的時候能實現漸變,也能幫助多線程控制等
我們知道,在VC的MFC中,已經為我們封裝好了很多全面和強大的函數集,所以在MFC編程時,巧妙地調用MFC函數庫可以為我們省去很多麻煩。其中定時器也可以在MFC程序中很好地利用。
在MFC中和定時器相關的有三個函數:
1.設置定時器(定義一個定時器的屬性):
SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT*lpfnTimer)(HWND,UINT,UINT,DWORD));
2.定時器響應(響應系統定義WM_TIMER消息):
OnTimer( UINT nIDEvent );
3.釋放定時器:
KillTimer( int nIDEvent );
其中:
UINT nIDEvent:定時器的ID,在一個程序中用這個ID來確定是那個定時器發送的消息。
UINT nElapse: 定義刷新時間,即間隔多長時間刷新一次,單位是毫秒。
void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD):回調函數的參數,實現刷新時所做的操作,一般情況下都設為0。
demo1
在這里就用一個簡單的例子來說明定時器在MFC中是如何使用的。
1.建立單文檔程序Timer。
2.在resource.h中定義兩個定時器的ID
#define TIMER1 1
#define TIMER2 2
3.在CMainFrame的OnCreate函數中定義兩個定時器的屬性。
SetTimer(TIMER1,3000,0);
SetTimer(TIMER2,5000,0);
4.在類視圖中右擊CMainFrame屬性,在消息響應函數中找到WM_TIMER,然后添加響應函數OnTimer()。
void CMainFrame::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default switch(nIDEvent) { case TIMER1: { AfxMessageBox("定時器1!"); break; } case TIMER2: { AfxMessageBox("定時器2!"); break; } default: break; } CFrameWnd::OnTimer(nIDEvent); }
5.在CMainFrame的析構函數中添加釋放定時器函數。
KillTimer(TIMER1);
KillTimer(TIMER2);
這樣,一個簡單的定時器程序就生成了,運行后可以看到,每隔3秒就會彈出一個消息對話框“定時器1”,每隔5秒就會彈出一個消息對話框“定時器2”。
這種情況是在程序運行后定時器就直接啟動了,很多時候我們需要的是在響應一次事件或者說點擊一個按鈕后再去執行定時器,那么這時應該怎么修改呢?也用一個實例來說明吧,因為我覺得可能說一大堆廢話也抵不上一個簡單而正確的實例更具說服力。
demo2
現在,我生成了一個MFC多文檔應用程序,我希望在點擊菜單條上的某個按鈕后再去執行定時器。這時就不是在CMainFrame里面操作了,因為我們是要在對話框上進行定時器的操作,而CView這個類是負責對話框的對應操作,所以要把定時器定義在CView里面。
1.建立多文檔程序Timer。
2.在resource.h中定義兩個定時器的ID
#define TIMER1 1
#define TIMER2 2
3.在CTimerView的OnInitialUpdate函數中定義兩個定時器的屬性。
SetTimer(TIMER1,3000,0);
SetTimer(TIMER2,5000,0);
4.在類視圖中右擊CTimerView屬性,在消息響應函數中找到WM_TIMER,然后添加響應函數OnTimer()。
void CTimerView::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default //Hwnd為一個變量,初始值為false,點擊某個按鈕后在其響應函數中將其置為true switch(nIDEvent && Hwnd){ case TIMER1: { AfxMessageBox("定時器1!"); break; } case TIMER2: { AfxMessageBox("定時器2!"); break; } default: break; } CFrameWnd::OnTimer(nIDEvent); }
5.在CTimerView中添加OnDestroy()函數,在函數中釋放定時器。
KillTimer(TIMER1);
KillTimer(TIMER2);
現在,運行程序后,沒有馬上彈出預定的對話框,而是在我們點擊某個按鈕或者響應某個事件后對話框才彈出,同樣是點擊按鈕后,每隔3秒彈出對話框“定時器1”,每隔5秒彈出“定時器2”。
其實在不同的類,定時器的用法都是基本一致的,只要找到類的初始函數和釋放函數,就能輕松實現定時功能了,就這么簡單。
demo3
基於對話框的定時器程序
1.打開VC,新建一基於對話框的工程,工程名為Test在對話框上添加一按鈕,將其ID改為IDC_BUTTON_START,Caption改為Start. 映像該按鈕的BN_CLICKED消息,void CTestDlg::OnButtonStart();
2.再在對話框上添加一按鈕,ID為ID_BUTTON_STOP,Caption改為Stop,映像消息為void CTestDlg::OnButtonStop();
3.添加一個Lable,ID改為IDC_STATIC_TIME,用於記數,表明定時器函數的執行。
4.映像對話框的WM_TIMER消息,void CTestDlg::OnTimer(UINT nIDEvent);
以上的實現函數如下所示:
void CTestDlg::OnButtonStart() { SetTimer(1,1000,NULL);//啟動定時器1,定時時間是1秒 } void CTestDlg::OnButtonStop() { KillTimer(1);//關閉定時器1。 } void CTestDlg::OnTimer(UINT nIDEvent) { static int nTimer=0; CString strTmp=""; strTmp.Format("Timer:%d",nTimer++); CWnd *pWnd=GetDlgItem(IDC_STATIC_TIME); pWnd->SetWindowText(strTmp); //在Lable中設置新值,表明定時器已經工作。 CDialog::OnTimer(nIDEvent); }
回調函數的使用。
如果不想使用窗體的WM_TIMER消息函數處理,可以使用回調函數來取代,讀者可以在上面例子的基礎上,增加一個回調函數,以證實前面的討論。
首先,定義一個回調函數,回調函數的定義必須按照如下格式。必須值靜態的
void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime );
我的實現函數如下:
void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime ) { AfxMessageBox("Timer is running!");//定時器時間到,強出一對話框,表明定時器已經運行。 }
將上面的啟動函數稍做修改
void CTestDlg::OnButtonStart() { //SetTimer(1,1000,NULL);//啟動定時器1,定時時間是1秒 SetTimer(1,1000,(TIMERPROC)TimerProc);//用回調函數處理,此時對話框的消息處理函數不再處理。 }
轉載自:http://my.oschina.net/ypimgt/blog/61061
程序員的基礎教程:菜鳥程序員