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)函數來建一個定時器,第三個參數就是回調函數地址。
 
2、多個定時器的實現與應用
 
咱們在安裝定時器時都爲其指定了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;
 }
}

  

3、取消定時器
 
再也不使用定時器後,咱們應該調用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 );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

 

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

相關文章
相關標籤/搜索