程序中我们经常要使用定时刷新的功能,典型的应用是在信息管理系统中表单要跟着数据库中的数据变动。MFC提供了定时器来完成这个功能。 在MFC中和定时器相关的有三个函数: UINT SetTimer( UINT nIDEvent">

MFC定时器

  • 格式:doc
  • 大小:38.50 KB
  • 文档页数:11

在/doc/">程序中我们经常要使用定时刷新的功能,典型的应用是在信息管理系统中表单要跟着数据库中的数据变动。

MFC提供了定时器来完成这个功能。

在MFC中和定时器相关的有三个函数:UINT SetTimer( UINT nIDEvent, UINT nElapse,void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD) );afx_msg void OnTimer( UINT nIDEvent );BOOL KillTimer( int nIDEvent );参数说明:UINT nIDEvent:定时器的ID,给定时器唯一的身份验证,如果在一个/doc/">程序中有多个定时器可以用这个ID来确定是那个定时器发送的消息。

UINT nElapse:定义刷新时间,即间隔多长时间刷新一次,单位是毫秒。

void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD):这个回调函数中实现刷新时所做的操作,如在数据库中读取数据。

但是我们大多数时候不在这里实现,而是在OnTimer中。

函数功能:SetTimer用来定义一个定时器的属性,如改定时器的ID,刷新时间,处理函数。

OnTimer实际时系统定义消息用来响应WM_TIMER消息,在这里可以实现对多定时器中的各个定时器分别响应,这里才时定时/doc/">程序大展宏图的地方。

字串2KillTimer用来结束一个定时器。

字串1下面我们用一个例子来说明定时器的使用:这个例子用来实现一个简单的功能,就是在一个单/doc/">文档/doc/">程序中,每间隔5秒弹出一个消息框提示“定时器1”,每隔7秒弹出一个消息框提示“定时器2”。

建立单/doc/">文档/doc/">程序略,一路Next。

(1)在resource.h中定义两个定时器的ID#define IDTIMER1 1#define IDTIMER2 2(2)在CMainFrame的OnCreate函数中定义两个定时器的属性。

SetTimer(TIMEID1,5000,0);SetTimer(TIMEID2,7000,0);(3) CMainFrame中对WM_TIMER进行响应。

void CMainFrame::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here and/or call default switch(nIDEvent) {case TIMEID1:{AfxMessageBox("定时器1!");break;} 字串1case TIMEID2:{AfxMessageBox("定时器2!");break;}default:;}CFrameWnd::OnTimer(nIDEvent);}(4)在CMainFrame的析构函数中添加KillTimer(IDTIMER1);KillTimer(IDTIMER2);本篇文章来源于忒好程序员| 原文链接:/html/doc/kfyy/20071226/1105.htmlTimer事件,即定时器事件,是在游戏编程中,经常使用的一个事件。

借助它可以产生定时执行动作的效果。

这篇文章,就和大家一起探讨一下如何使用SetTimer()函数。

1、SetTimer定义在那里?SetTimer表示的是定义个定时器。

根据定义指定的窗口,在指定的窗口(CWnd)中实现OnTimer事件,这样,就可以相应事件了。

SetTimer有两个函数。

一个是全局的函数::SetTimer()UINT SetTimer(HWND hWnd, // handle of window for timer messagesUINT nIDEvent, // timer identifierUINT uElapse, // time-out valueTIMERPROC lpTimerFunc // address of timer procedure);其中hWnd 是指向CWnd的指针,即处理Timer事件的窗口类。

说道窗口类(CWnd),我们有必要来看一下CWnd的继承情况:CWnd有以下子类:CFrameWnd,CDialog,CView,CControlBar等类。

这也意味这些类中都可以定义SetTimer事件。

同时,SetTimer()在CWnd中也有定义,即SetTimer()是CWnd的一个成员函数。

CWnd的子类可以调用该函数,来设置触发器。

UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );参数含义:nIDEvent:是指设置这个定时器的iD,即身份标志,这样在OnTimer()事件中,才能根据不同的定时器,来做不同的事件响应。

这个ID是一个无符号的整型。

nElapse是指时间延迟。

单位是毫秒。

这意味着,每隔nElapse毫秒系统调用一次Ontimer()。

void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD)Specifies the address of the application-suppliedTimerProccallback function that processes the WM_TIMER messages. If this parameter is NULL, theWM_TIMER messages are placed in the applic ation’s message queue and handled by the CWnd object。

意思是,指定应用程序提供的TimerProc回调函数的地址,来处里这个Timer事件。

如果是NULL,处理这个Timer事件的定义这个Timer的CWnd对象。

他将WM_TIMER消息传递给这个对象,通过实现这个对象的OnTimer()事件来处理这个Timer事件。

所以,一般情况下,我们将这个值设为NULL,有设置该定时器的对象中的OnTimer()函数来处理这个事件。

同样的,我们再看看KillTimer()和OnTimer()的定义:KillTimer同SetTimer()一样,他也有两个,一个是全局的::KillTimer(),另一个是CWnd的一个函数。

他的声明如下://全局函数BOOL KillTimer(HWND hWnd, // handle of window that installed timerUINT uIDEvent // timer identifier);//CWnd函数BOOL KillTimer( int nIDEvent );这两个函数表示的意思是将iD为nIDEVENT的定时器移走。

使其不再作用。

其用法如同SetTimer ()一样。

再看看OnTimer()afx_msg void OnTimer( UINT nIDEvent );ontimer()是响应CWnd对象产生的WM_Timer消息。

nIDEvent表示要响应TIMER事件的ID。

二、Timer事件的使用:由以上的分析,我们应该很清楚,如何来使用Timer事件。

假定我们在视图上画一个渐变的动画。

我们首先在菜单栏上添加一个菜单项,给这个菜单添加命令响应:pView->SetTimer(1,1000,NULL);//pView是视图类的指针,这里是在视图类当中设置一个定时器。

添加完毕,再给视图类添加一个WM_Timer事件的相应。

在OnTimer()函数中编写汉书,进行相应。

如此,就能做出动画。

用多媒体定时器微软公司在其多媒体Windows中提供了精确定时器的底层API支持。

利用多媒体定时器可以很精确地读出系统的当前时间,并且能在非常精确的时间间隔内完成一个事件、函数或过程的调用。

利用多媒体定时器的基本功能,可以通过两种方法实现精确定时。

1.使用timeGetTime()函数该函数定时精度为ms级,返回从Windows启动开始所经过的时间。

由于使用该函数是通过查询的方式进行定时控制的,所以,应该建立定时循环来进行定时事件的控制。

2. 使用timeSetEvent()函数利用该函数可以实现周期性的函数调用。

函数的参数说明如下:uDelay:延迟时间;uResolution:时间精度,在Windows中缺省值为1ms;lpFunction:回调函数,为用户自定义函数,定时调用;dwUser:用户参数;uFlags:标志参数;TIME_ONESHOT:执行一次;TIME_PERIODIC:周期性执行。

具体应用时,可以通过调用timeSetEvent()函数,将需要周期性执行的任务定义在lpFunction回调函数中(如:定时采样、控制等),从而完成所需处理的事件。

需要注意的是:任务处理的时间不能大于周期间隔时间。

另外,在定时器使用完毕后,应及时调用timeKillEvent()将之释放。

下面这段代码的主要功能是设置两个时钟定时器,一个间隔是1ms,一个间隔是2s。

每执行一次,把当前系统时钟值输入文件“cure.out”中,以比较该定时器的精确度。

//定义1ms和2s时钟间隔,以ms为单位#define ONE_MILLI_SECOND 1#define TWO_SECOND 2000//定义时钟分辨率,以ms为单位#define TIMER_ACCURACY 1//定义时间间隔UINT wTimerRes_1ms,wTimerRes_2s;//定义分辨率UINT wAccuracy;//定义定时器句柄UINT TimerID_1ms,TimerID_2s;//打开输出文件“cure.out”CCureApp::CCureApp():fout(“cure.out”, ios::out){// 给时间间隔变量赋值wTimerRes_1ms = ONE_MILLI_SECOND;wTimerRes_2s = TWO_SECOND;TIMECAPS tc;//利用函数timeGetDevCaps取出系统分辨率的取值范围,如果无错则继续if(timeGetDevCaps(&tc,sizeof(TIMECAPS))==TIMERR_NOERROR) {//分辨率的值不能超出系统的取值范围wAccuracy=min(max(tc.wPeriodMin,TIMER_ACCURACY),tc.wPeriodMax);//调用timeBeginPeriod函数设置定时器的分辨率timeBeginPeriod(wAccuracy);//设置定时器InitializeTimer();}}CCureApp:: ~CCureApp(){//结束时钟fout <<“结束时钟”<< endl;// 删除两个定时器timeKillEvent(TimerID_1ms);timeKillEvent(TimerID_2s);// 删除设置的分辨率timeEndPeriod(wAccuracy);}void CCureApp::InitializeTimer(){StartOneMilliSecondTimer();StartTwoSecondTimer();}// 1ms定时器的回调函数,类似于中断处理程序,一定要声明为全局PASCAL函数,否则编译会有问题void PASCAL OneMilliSecondProc(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2){// 定义计数器static int ms = 0;CCureApp *app = (CCureApp *)dwUser;// 取得系统时间,以ms为单位DWORD osBinaryTime = GetTickCount();//输出计数器值和当前系统时间app->fout<<++ms<<“:1ms:”<}// 加装1ms定时器void CCureApp::StartOneMilliSecondTimer(){if((TimerID_1ms = timeSetEvent(wTimerRes_1ms,wAccuracy,// 回调函数(LPTIMECALBACK) OneMil liSecondProc,// 用户传送到回调函数的数据(DWORD)this,/ *周期调用,只使用一次,用TIME_ONESHOT*/TIME_PERIODIC)) == 0){AfxMessageBox(“不能进行定时!”, MB_OK | MB_ICONASTERISK); }else //不等于0表明加装成功,返回此定时器的句柄fout << “16ms 计时:” << endl; }。