MFC 定时器用法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

MFC中定时器的使用
在/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/">程序大展宏图的地方。 字串2

KillTimer用来结束一个定时器。 字串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;

} 字串1

case TIMEID2:

{

AfxMessageBox("定时器2!");

break;

}

default:

;

}



CFrameWnd::OnTimer(nIDEvent);

}

(4)在CMainFrame的析构函数中添加

KillTimer(IDTIMER1);

KillTimer(IDTIMER2);

本篇文章来源于 忒好程序员| 原文链接:/html/doc/kfyy/20071226/1105.html



Timer事件,即定时器事件,是在游戏编程中,经常使用的一个事件。借助它可以产生定时执行动作的效果。这篇文章,就和大家一起探讨一下如何使用SetTimer()函数。

1、SetTimer定义在那里?

SetTimer表示的是

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

SetTimer有两个函数。一个是全局的函数::SetTimer()

UINT SetTimer(

HWND hWnd, // handle of window for timer messages

UINT nIDEvent, // timer identifier

UINT uElapse, // time-out value

TIMERPROC 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-supplied

TimerProc

callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application’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 timer

UINT 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;

}


相关文档
最新文档