关闭

MFC中定时器的使用

719人阅读 评论(0) 收藏 举报

在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);

本篇文章来源于 忒好程序员|www.teihao.com 原文链接:http://www.teihao.com/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;     

}    

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:102066次
    • 积分:1466
    • 等级:
    • 排名:千里之外
    • 原创:28篇
    • 转载:56篇
    • 译文:0篇
    • 评论:12条
    文章分类
    最新评论