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);程序員
——————————————————————————————————————————————————編程
巧妙地使用定時器能達到意想不到的效果,寫界面的時候能實現漸變,也能幫助多線程控制等
咱們知道,在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 );spa
3.釋放定時器:
KillTimer( int nIDEvent );.net
其中:
UINT nIDEvent:定時器的ID,在一個程序中用這個ID來肯定是那個定時器發送的消息。
UINT nElapse: 定義刷新時間,即間隔多長時間刷新一次,單位是毫秒。
void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD):回調函數的參數,實現刷新時所作的操做,通常狀況下都設爲0。線程
demo1code
在這裏就用一個簡單的例子來講明定時器在MFC中是如何使用的。
1.創建單文檔程序Timer。orm
2.在resource.h中定義兩個定時器的ID
#define TIMER1 1
#define TIMER2 2blog
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
程序員的基礎教程:菜鳥程序員