WM_TIMER学习

 

Windows WM_TIMER消息  

2010-11-19 09:53:00|  分类:MFC|  标签:|字号 订阅

Windows定时器是一种周期性的消息产生装置,它会每隔一段指定时间发送一次定时消息WM_TIMER。它是一个很重要的系统消息,当系统所设置的时间到达以后,系统就会自动发送该消息。与该消息联系密切的函数是SetTimer(),它设置一个系统时钟,当设置的时间到时,系统产生WM_TIMER消息。通过对SetTimer()函数的参数进行设置,可以告诉用户哪一个时钟的时间到了。因此,可以将一些周期性的工作放入WM_TIMER的消息处理函数中。

定时器的使用一般遵循下列步骤:

(1)使用SetTimer()函数设置定时器

SetTimer()函数的原型如下: 

UINT SetTimer(UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT*lpfnTimer)(HWNDUINT, UINT, DWORD)); 

其中,参数nIDEvent为新创建的定时器标识号码(非零),当一个应用程序需要多个定时器时,靠此参数的不同来加以区别;参数nElapse为定时器间隔,以毫秒为单位,当由该参数规定的时间到后,系统发送WM_TIMER消息;参数lpfnTimer为指定处理消息WM_TIMER的函数,通常为NULL时,表示由CWnd对象的OnTimer成员函数来处理该消息,当然也可以超载该函数。

SetTimer(m_hWnd,1,1000,NULL); //一个1秒触发一次的定时器

如果创建成功,则返回新的定时器的号码:否则返回0

(2)超载OnTimer()函数,完成用户希望的操作

通过第一步设置的定时器会按其设置的时间间隔向应用程序发送WM_TIMER消息,为了接收和处理该消息,应超载消息处理函数OnTimer()(可以由ClassWizard自动产生),其函数原型如下: 

afx_msg void OnTimer(UINT nIDEvent); 

其中,参数nIDEvent为定时器的标识。若在程序中设置了多个定时器时,靠此参数的不同来加以区别。

(3)撤销定时器 

定时器使用完后,可以通过调用KillTimer()函数来清除定时器,其函数原型如下: 

BOOL KillTimer(int nIDEvent);

   说明:销毁以前调用SetTimer创建的用nIDEvent标识的定时器事件。任何与此定时器有关的未处理的WM_TIMER消息都从消息队列中清除。 

其中,参数nIDEvent为准备清除的定时器号码,该参数的值必须在SetTimer()函数中设置过,即不能够清除一个不存在的定时器号码。传递给SetTimer的定时器事件值。

【例9.4本程序在例9.3程序的基础上增加定时器的功能。当按B键时,启动定时器,屏幕上的图形自动移动;当按S键时,撤销定时器,停止自动移动。

(1)在字符消息映射函数中添加启动和撤销定时器的代码 

void CKeyMsgView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

   switch(nChar){

case 'b':

case 'B':

SetTimer(1,100,NULL); //建立一号定时器,时间间隔为100ms

break;

case 's':

case 'S':

KillTimer(1); //撤销一号定时器

break;

}

}

 

(2)添加WM_TIMER的消息映射函数OnTimer()的实现代码

 

void CKeyMsgView::OnTimer(UINT nIDEvent)

{

//图形往右下角自动移动

CRect OldRect=m_Rect;

m_Rect.OffsetRect(CPoint(1,1)); //图形往右下角移动一个像素

OldRect.UnionRect(OldRect,m_Rect);

InvalidateRect(OldRect); //将指定矩形区域OldRect的内容刷新

CView::OnTimer(nIDEvent);

} 

TimerProc函数是一个应用程序定义的回调函数,用于处理WM_TIMER消息。

 

函数原型:

VOID CALLBACK TimerProc(

   HWND hwnd,// 定时器消息的窗口句柄

   UINT uMsg,   // WM_TIMER 消息

   UINT idEvent,// 定时器标识符

   DWORD dwTime  // 当前系统时间

  );

 

参数说明:

hwnd

       标识了与定时器进行关联的窗口。 

uMsg

       指定WM_TIMER消息。

idEvent

       指定定时器的标识符。 

dwTime

       指定自窗口启动开始所经过的毫秒数。这是GetTickCount函数的返回值。

返回值: 

       这个函数没有返回值。

备注: 

TimerProc是一个应用程序定义函数名称的占位符。

例:

  1) 不用回调函数

  SetTimer(1,1000,NULL);

  1:计时器的名称;

  1000:时间间隔,单位是毫秒;

  NULL:使用onTime函数。

  当不需要计时器的时候调用KillTimer(nIDEvent);

  例如:KillTimer(1);

  2) 调用回调函数

  此方法首先写一个如下格式的回调函数

  void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime);

  然后再用SetTimer(1,100,TimerProc)函数来建一个定时器,第三个参数就是回调函数地址。

  或许你会问,如果我要加入两个或者两个以上的 timer怎么办?

  继续用SetTimer函数吧,上次的timer的ID是1,这次可以是2,3,4。。。。

  SetTimer(2,1000,NULL);

  SetTimer(3,500,NULL);

  嗯,WINDOWS会协调他们的。当然onTimer函数体也要发生变化,要在函数体内添加每一个timer的处理代码:

  onTimer(nIDEvent)

  {

  switch(nIDEvent)

  {

  case 1:........;

  break;

  case 2:.......;

  break;

  case 3:......;

  break;

  }

  }

例3:

1.       每隔1s刷新当前启动的时间,按开始测试按钮,开始计时并且显示测试所用时间,停止按钮停止测试,再次点击开始按钮,从0开始记录。

OnBnClickedBtnStart()函数

     TestStartTime      = CTime::GetCurrentTime();

     SetTimer(TEST_TOTAL_TIME, 1000, NULL);

     GetDlgItem(IDC_STC_TEST_TOTAL_TIME)->SetWindowText("00:00:00");

void CCLMemTestDlg::OnTimer(UINT_PTR nIDEvent)

{

     // TODO: Add your message handler code here and/or call default

     CTimeSpan TestTime; //可用于显示时间差

     CTime CurrentTime = CTime::GetCurrentTime();

     TestTime = CurrentTime - TestStartTime;  //测试时间

     CString Str,Str_Start,Str_Current;

     Str_Current = CurrentTime.Format("%H:%M:%S");

     Str_Start = TestStartTime.Format("%H:%M:%S");

     Str = TestTime.Format("%H:%M:%S");

     GetDlgItem(IDC_STC_TEST_TOTAL_TIME)->SetWindowText(Str);

     CDialog::OnTimer(nIDEvent);

}按停止测试按钮,停止计时显示时间

KillTimer(1)

再按下开始测试按钮,重新归零开始计时并且显示时间

 

你可能感兴趣的:(windows,timer,测试,null,callback,图形)