MFC定时器的应用

时间:2023-02-03 00:22:22
  在计算机程序设计领域,有很多功能是周期性执行的,       如:数据采集程序,系统时间的显示等。 数据采集:周期性地获得现场的物理量信息系统时间的显示:周期性地获得系统时间,并显示出来。 完成上述这些功能的代码都是按照一定的时间间隔周期性地执行的,这是就需要用到一个新的组件——定时器(TIMER)。       定时器是Windows系统的资源, Visual C++提供了定时器消息和一些与定时相关的函数。使用这些函数可以完成程序代码的周期性执行。Viusal C++提供了三种完成周期性操作的方法: 1、Sleep函数(延时函数)。 2、WM_TIMER消息(Windows窗口消息)。 3、多媒体定时器。 3.2.1 Sleep函数while(1)   {   i=i+1; //此处添加需要周期性执行的代码。  Sleep(1000); } Sleep函数:延时函数 参数:延时的时间(单位ms)缺点: (1)CPU占用率高,一般适用于单任务的程序(如DOS操作系统的程序) (2)程序能够完成的功能比较简单。 (3)定时精度低,(据资料)最小误差为54.915 ms,每秒18.2次3.2.2 WM_TIMER众所周知,Windows系统是一个多任务的操作系统。即可以有多个任务并行,这时,周期性(定时)执行的任务在执行完毕后,应该将控制权交给系统,这样程序的其它功能才能得以执行。Windows系统提供了WM_TIMER消息来实现多任务系统的定时操作。     WM_TIMER是一个Windosws的窗口消息 1、WM_TIMER的功能:     (1)可以完成定时操作。     (2)定时任务执行完毕后,将控制权交回给程序。程序可以进行其它的操作。  2、使用WM_TIMER消息需要用到的函数1) SetTimer()功能:设置定时间隔并启动定时器。函数原型:UINT SetTimer(UINT nIDEvent,UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD));参数说明: nIDEvent:非0值标识Timer的id 。 nElapse:以毫秒为单位的定时间隔时间 lpfnTimer 指向定时事件到达时调用的函数的指针,如果为NULL,那么调用OnTimer() 例:SetTimer(1,200,NULL)设置并启动一个时间间隔为200ms的定时器。消息响应函数为OnTimer() 例:SetTimer(2,1000, TimerProc );设置并启动一个实间间隔为1s的定时器,该定时器的响应函数为TimerProc。 2)KillTimer(1)功能:取消定时器,此函数调用后,相应的定时器将被关闭不再起作用。 参数:用SetTimer()函数创建的定时器标识。 定时器使用总结: 1、在WM_CREATE消息中启动定时器(SetTimer) 2、在WM_TIMER消息中编写定时函数(即需要周期性完成的工作) 3、在定时工作完成之后关闭/停止定时器。(可选)WM_TIMER的缺点: 1、精度低,最小计时精度大约为55ms(Win95),或10ms左右(Win2000/xp)2、定时器消息在多任务操作系统中的优先级较低,有时不能得到及时响应。(一旦计算机的CPU被某个进程占用,或系统资源紧张时,发送到消息队列中的消息就暂时被挂起,WM_TIMER消息得不到及时处理。)3.2.3 多媒体定时器1、 针对前两种定时器的缺点,MicroSoft公司提供了一种精度更高的定时器——多媒体定时器。优点: (1)精度较高:多媒体定时器最小误差为1毫秒。 (2)优先级较高,可以减轻资源紧张对定时器运行的影响。2、多媒体定时器的使用timeSetEvent 函数 功能:设置并启动一个多媒体定时器。 函数原型: MMRESULT timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, WORD dwUser, UINT fuEvent )函数头文件:#include "mmsystem.h"MMRESULT timeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, WORD dwUser, UINT fuEvent )参数说明:uDelay:以毫秒指定时的周期Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。 LpTimeProc:指向一个回调函数,该回调函数包含需要定时执行的代码。DwUser:存放用户提供的回调数据。FuEvent:指定定时器事件类型:     TIME_ONESHOT:uDelay毫秒后只产生一次事件。     TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。 3.3 其它定时方法1、使用GetTickCount函数 2、使用QueryPerformanceFrequency()和QueryPerformanceCounter()函数。 在精度要求较高的情况下,如要求定时误差不大于1ms时,还可以利用GetTickCount()函数返回自计算机启动后的时间,该函数的返回值是DWORD型,表示以ms为单位的计算机启动后经历的时间间隔。通过两次调用GetTickCount()函数,然后控制它们的差值来取得定时效果。.下列的代码可以实现50ms的精确定时,其误差是毫秒级的。3、使用QueryPerformanceFrequency()和QueryPerformanceCounter()函数     对于更精确的定时操作,使用QueryPerformanceFrequency()和QueryPerformanceCounter()函数。这两个函数是Visual C++提供并且仅供Windows 95及其后续版本使用,其精度与CPU的时钟频率有关,它们要求计算机从硬件上支持精确定时器。QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型如下:BOOL QueryPerformanceFrequency (LARGE_INTEGER *lpFrequency);
BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);
使用QueryPerformanceFrequency()和QueryPerformanceCounter()函数进行精确定时的步骤如下:
  1、首先调用QueryPerformanceFrequency()函数取得高精度运行计数器的频率f,单位是每秒多少次(n/s),此数一般很大;
  2、在需要定时的代码的两端分别调用QueryPerformanceCounter()以取得高精度运行计数器的数值n1、n2,两次数值的差值通过f换算成时间间隔,t=(n2-n1)/f,当t大于或等于定时时间长度时,启动定时器;