VC++ 定時器使用總結


VC++    WM_TIMER   定時器使用方法
      在編程時,會經常使用到定時器。使用定時器的方法比較簡單,通常告訴Windows一個時間間隔,然后WINDOWS以此時間間隔周期性觸發程序。通常有兩種方法來實現:發送WM_TIMER消息和調用應用程序定義的回調函數。
 
1.1 用WM_TIMER來設置定時器
 
先請看SetTimer這個API函數的原型
 
UINT_PTR SetTimer(
HWND hWnd, // 窗口句柄
UINT_PTR nIDEvent, // 定時器ID,多個定時器時,可以通過該ID判斷是哪個定時器
UINT uElapse, // 時間間隔,單位為毫秒
TIMERPROC lpTimerFunc // 回調函數
);

  

 
例如 :
SetTimer(m_hWnd,1,1000,NULL); //一個1秒觸發一次的定時器
在MFC程序中SetTimer被封裝在CWnd類中,調用就不用指定窗口句柄了,例如:
UINT SetTimer(1,100,NULL);
函數反回值就是第一個參數值1,表示此定時器的ID號。
 
第二個參數表示要等待100毫秒時間再重新處理一次。第三個參數在這種方法中一般用NULL。
注意:設置第二個參數時要注意,如果設置的等待時間比處理時間短,程序就會出問題了。
 
1.2 調用回調函數
 
此方法首先寫一個如下格式的回調函數
 
void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime);
然后再用SetTimer(1,100,TimerProc)函數來建一個定時器,第三個參數就是回調函數地址。
 
二、多個定時器的實現與應用
 
我們在安裝定時器時都為其指定了ID,使用多個定時器時,該ID就發揮作用了。
不使用MFC時,當接收到WM_TIMER消息,WPARAM wParam中的值便是該定時器的ID
使用MFC時就更簡單了,我們為其增加WM_TIME的消息處理函數OnTimer即可,請看如下例子 
void CTimerTestDlg::OnTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case 24: ///處理ID為24的定時器
 Draw1();
 break;
case 25: ///處理ID為25的定時器
 Draw2();
 break;
}
CDialog::OnTimer(nIDEvent);
}

  

當你用回調函數時,我們可以根據nTimerid的值來判斷是哪個定時器,例如:
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來取消定時,KillTimer的原型如下
 
BOOL KillTimer(
HWND hWnd, // 窗口句柄
UINT_PTR uIDEvent // ID
);
在MFC程序中我們可以直接調用KillTimer(int nIDEvent)來取消定時器。
 

如: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

 

程序員的基礎教程:菜鳥程序員


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM