VC高精度定时

时间:2021-11-29 08:52:28


一、VC实现高精度定时器__基本流程
  1、头文件包含        #include <MMSystem.h>
    
  2、类成员中添加变量    UINT   m_iTimerId; //定时器句柄   
    
  3、创建回调函数,响应定时器事件
    void   CALLBACK   CatchTimer
        ( UINT    IDEvent,
          UINT    uReserved,
          DWORD    dwUser,
          DWORD    dwReserved1,
          DWORD    dwReserved2)
    {  //在这里写定时器事件的处理  }   
    
  4、开始启动定时器
    //设置定时器分辨率,1ms   
    timeBeginPeriod(1);   

    //产生间隔100毫秒,周期执行的定时器事件;启动定时器   
     m_iTimerId=timeSetEvent(1,100,CatchTimer,(DWORD)this->m_hWnd,TIME_PERIODIC);   
    
    
  5、结束使用定时器   
    //删除定时器事件   
    if(m_iTimerId)   
    timeKillEvent(m_iTimerId);   
    //清除定时器分辨率   
    timeEndPeriod(1);   

设置两个时钟定时器,一个间隔是1毫秒,一个间隔是2秒,
每执行一次,输出当前系统时钟值到文件“cure.out”,以 比较此定时器的精确度。
(此程序在中文windows95及Microsoft VC5.0编译通过。只节取与定时器有关的部分程序。)     

#include   <   stdio.h   >   
  //包含所用系统函数的头文件,   
  如果编译有问题,可调整此语句的位置   
  #include   <   mmsystem.h   >   
    
  //定义1毫秒和2秒时钟间隔,以毫秒为单位   
  #define ONE_MILLI_SECOND1   
  #define TWO_SECOND 2000   
  //定义时钟分辨率,以毫秒为单位   
  #define TIMER_ACCURACY1   
    
  UINT   wTimerRes_1ms,wTimerRes_2s;     //定义时间间隔   
  UINT   wAccuracy;//定义分辨率   
  UINT   TimerID_1ms,TimerID_2s;//定义定时器句柄   
    
  CCureApp::CCureApp()   
  :   fout("cure.out",   ios::out)//打开输出文件“cure.out”   
  {   
  //   TODO:   add   construction   code   here,   
  //   Place   all   significant   
                initialization   in   InitInstance   
  //给时间间隔变量赋值   
  wTimerRes_1ms   =   ONE_MILLI_SECOND ;   
  wTimerRes_2s   =   TWO_SECOND;   
    
  TIMECAPS   tc;   
  //通过函数timeGetDevCaps取出系统   
  的分辨率取值范围(对intel系统,   
  1~16毫秒),//如果无错则继续   
  if(timeGetDevCaps(&tc,   sizeof(TIMECAPS))   
  ==   TIMERR_NOERROR)   
  {   
  //分辨率的值不能超出系统的取值范围   
  wAccuracy   =   min(max(tc.wPeriodMin,   
  TIMER_ACCURACY),tc.wPeriodMax);   
  //调用timeBeginPeriod函数设置定时器   
  的分辨率,类似于for循环的步长   
  timeBeginPeriod(wAccuracy);   
  //设置定时器   
  InitializeTimer();   
  }   
  }   
    
  CCureApp::~CCureApp()   
  {   
  //结束时钟   
  fout   <   <     "结束时钟"   <   <     endl;   
  //删除两个定时器   
  timeKillEvent(TimerID_1ms);   
  timeKillEvent(TimerID_2s);   
  //删除设置的分辨率   
  timeEndPeriod(wAccuracy);   
  }   
  注:使用完的定时器及分辨率一定   
  要删除,否则系统会越来越慢。   
    
  void CCureApp::InitializeTimer()   
  {   
  StartOneMilliSecondTimer();   
  StartTwoSecondTimer();   
  }   
    
  //一毫秒定时器的回调函数,   
  类似于中断处理程序   
  voidPASCAL//一定要声明为全局PASCAL函数,   
  否则编译会有问题   
  OneMilliSecondProc(UINT wTimerID,   UINT   msg,   
  DWORD dwUser,   DWORD   dw1,   DWORD   dw2)   
  {   
  static int ms   =   0;//定义计数器   
  CCureApp *app   =   (CCureApp   *)dwUser;   
  //取得系统时间以毫秒为单位   
  DWORD   osBinaryTime   =   GetTickCount();   
  //输出计数器值和当前系统时间到文件   
  app-   >fout   <   <     ++ms   <   <     ":   1ms   :   "   
    <   <     osBinaryTime   <   <     endl;   
  }   
    
  //加装1毫秒定时器   
  void   CCureApp::StartOneMilliSecondTimer()   
  {   
  if((TimerID_1ms   =   timeSetEvent(wTimerRes_1ms,   wAccuracy,   
    (LPTIMECALLBACK)   OneMilliSecondProc,//回调函数   
    (DWORD)this,//用户自传送到回调函数的数据   
  /*周期调用,只使用一次用TIME_ONESHOT*/   
  TIME_PERIODIC))   ==   0)   
  {   
  AfxMessageBox("不能计时",   MB_OK   |   MB_ICONASTERISK);   
  }   
  else//不等于0表明加装成功,   
  返回此定时器的句柄   
  fout   <   <     "16ms计时:"   <   <     endl;   
  }   
    
  以下为2秒定时器的回调函   
  数和加装函数,与1毫秒的类似;   
  void   PASCAL   
  TwoSecondProc(UINT wTimerID,   UINT   msg,   
      DWORD dwUser,   DWORD   dw1,   DWORD   dw2)   
  {   
  static int s   =   0;   
  CCureApp *app   =   (CCureApp   *)dwUser;   
  DWORD   osBinaryTime   =   GetTickCount();   
  app-   >fout   <   <     "***********************   
  ***********************"   <   <     endl;   
  app-   >fout   <   <     ++s   <   <     ":   2s   :   "   
    <   <     osBinaryTime   <   <     endl;   
  }   
    
  void CCureApp::StartTwoSecondTimer()   
  {   
  if((TimerID_2s   =   timeSetEvent(wTimerRes_2s,   wAccuracy,   
    (LPTIMECALLBACK)   TwoSecondProc,   
    (DWORD)this,   
      TIME_PERIODIC))   ==   0)   
  {   
  AfxMessageBox("不能计时",   MB_OK   |   MB_ICONASTERISK);   
  }   
  else   
  fout   <   <     "2s计时:"   <   <     endl;   
  }     

timeSetEvent函数原型

 1 MMRESULT timeSetEvent( UINT uDelay,
 2                                  UINT uResolution,
 3                                  LPTIMECALLBACK lpTimeProc,
 4                                  WORD dwUser,
 5                                  UINT fuEvent )
 6 
 7         uDelay:以毫秒指定事件的周期。
 8          Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。
 9          LpTimeProc:指向一个回调函数。
10          DwUser:存放用户提供的回调数据。
11          FuEvent:指定定时器事件类型:
12          TIME_ONESHOT:uDelay毫秒后只产生一次事件
13          TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。

可以同时设置多个定时器:

 1 m_iTimerId = timeSetEvent(1000,1,CatchTimer,(DWORD)this->m_hWnd,TIME_PERIODIC);   
 2 
 3     m_iTimerId2 = timeSetEvent(5000,1,CatchTimer,(DWORD)this->m_hWnd,TIME_PERIODIC);   
 4 
 5     theApp.id1 = m_iTimerId;
 6     theApp.id2 = m_iTimerId2;
 7 
 8 
 9 void   CALLBACK   CatchTimer
10     ( UINT    IDEvent,
11     UINT    uReserved,
12     DWORD    dwUser,
13     DWORD    dwReserved1,
14     DWORD    dwReserved2) 
15 {
16     if (IDEvent == theApp.id1)
17     {
18         MessageBoxA(0,"A",0, 0);
19     } 
20     else
21     {
22         if (IDEvent == theApp.id2)
23         {
24             MessageBoxA(0,"B",0, 0);
25         }
26     }
27 
28     
29     static int n = 0;
30     n++;
31     CString str;
32     str.Format("%d", n);
33     theApp.pEdit->SetWindowText(str);
34 
35 }