VC++中计时器的运用

转载 2007年12月19日 09:27:00
 
1、MFC中的计时原理:
当你需要每隔一段时间执行一件事的的时候就需要使用SetTimer()函数了。 让我们先来看看SetTimer函数的原型:
    UINT SetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACK EXPORT *lpfnTimer)(HWND,UINT ,YINT ,DWORD))
当使用SetTimer函数的时候,就会生成一个计时器。函数中nIDEvent指的是计时器的标识,也就是名字。nElapse指的是时间间隔,也就是每隔多长时间触发一次事件。第三个参数是一个回调函数,在这个函数里,放入你想要做的事情的代码,你可以将它设定为NULL,也就是使用系统默认的回调函数,系统默认认的是onTime()函数。这个函数怎么生成的呢?你需要在需要计时器的类的生成onTime函数:在ClassWizard里,选择需要计时器的类,添加WM_TIME消息映射,就自动生成onTime函数了。然后在函数里添加代码,让代码实现功能。每隔一段时间就会自动执行一次。例: SetTimer(1,1000,NULL); 其中,1为计时器的名称; 1000为时间间隔,单位是毫秒; NULL指使用onTime函数。
如果最后一个参数不是NULL,就调用TimerProc(),原型为:
void CALLBACK EXPORT TimerProc(
   HWND hWnd,      // handle of CWnd that called SetTimer
   UINT nMsg,      // WM_TIMER
   UINT nIDEvent   // timer identification
   DWORD dwTime    // system time
){}
 
 当不需要计时器的时候调用KillTimer(nIDEvent); 例如:KillTimer(1); 或许你会问,如果我要加入两个或者两个以上的 timer怎么办? 继续用SetTimer函数吧,上次的timer的ID是1,这次可以是2,3,4。。。。 SetTimer(2,1000,NULL); SetTimer(3,500,NULL); 嗯,WINDOWS会协调他们的。当然onTimer函数体也要发生变化,要在函数体内添加每一个timer的处理代码: onTimer(nIDEvent) { switch(nIDEvent) { case 1:........; break; case 2:.......; break; case 3:......; break; } }
小技巧:可以使用#define定义不同的计时器ID值。
#define TIME_SEC 1
#define TIME_MIN 2
然后调用SetTimer设定两个计时器
SetTimer (hwnd, TIMER_SEC, 1000, NULL) ;SetTimer (hwnd, TIMER_MIN, 600, NULL)
2、API函数
(1)、SetTimer函数用于创建一个计时器,KillTimer函数用于销毁一个计时器。计时器属于系统资源,使用完应及时销毁。
SetTimer的函数原型如下:
UINT_PTR SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc ) ;
  其中
  hWnd是和timer关联的窗口句柄,此窗口必须为调用SetTimer的线程所有;如果hWnd为NULL,没有窗口和timer相关联并且nIDEvent参数被忽略
  nIDEvent是timer的标识,为非零值;如果hWnd为NULL则被忽略;如果hWnd非NULL而且与timer相关联的窗口已经存在一个为此标识的timer,则此次SetTimer调用将用新的timer代替原来的timer。timer标识和窗口相关,两个不同的窗口可以拥有nIDEvent相同的timer
  uElapse是以毫秒指定的计时间隔值,范围为1毫秒到4,294,967,295毫秒(将近50天),这个值指示Windows每隔多久时间给程序发送WM_TIMER消息。
  lpTimerFunc是一个回调函数的指针,俗称TimerFunc;如果lpTimerFunc为NULL,系统将向应用程序队列发送WM_TIMER消息;如果lpTimerFunc指定了一个值,DefWindowProc将在处理WM_TIMER消息时调用这个lpTimerFunc所指向的回调函数,因此即使使用TimerProc代替处理WM_TIMER也需要向窗口分发消息。
关于SetTimer的返回值:如果hWnd为NULL,返回值为新建立的timer的ID,如果hWnd非NULL,返回一个非0整数,如果SetTimer调用失败则返回0
KillTimer的函数原型为:BOOL KillTimer( HWND hWnd, UINT_PTR uIDEvent ) ; 参数意义同SetTimer。
  关于KillTimer对消息队列中剩余未处理的WM_TIMER消息的影响,MSDN和Programming Windows上的说法完全相反。MSDN的说法很干脆:The KillTimer function does not remove WM_TIMER messages already posted to the message queue. 而petzold则说 The KillTimer call purges the message queue of any pending WM_TIMER messages. Your program will never receive a stray WM_TIMER message following a KillTimer call.(KillTimer消除消息队列中任何未处理的WM_TIMER消息,调用KillTimer后你的程序永远不会收到一条“漂泊游荡”的WM_TIMER消息)
2)、关于WM_TIMER消息
wParam为计时器的ID;如果需要设定多个计时器,那么对每个计时器都使用不同的计时器ID。wParam的值将随传递到窗口过程中的WM_TIMER消息的不同而不同。
  lParam为指向TimerProc的指针,如果调用SetTimer时没有指定TimerProc(参数值为NULL),则lParam为0(即NULL)。
  可以通过在窗口过程中提供一个WM_TIMER case处理这个消息,或者,默认窗口过程会调用SetTimer中指定的TimerProc来处理WM_TIMER消息
(3)、使用计时器的三种方法
如果在程序的整个执行过程中使用计时器,一般在处理WM_CREATE消息时或WinMain中消息循环前调用SetTimer,在处理WM_DESTROY消息时或在WinMain中消息循环后return前调用KillTimer。根据SetTimer中的参数不同,有三种方法使用计时器。
方法一:调用SetTimer时指定窗口句柄hWnd,nIDEvent中指定计时器ID,将lpTimerFunc置NULL从而不使用TimerProc;在窗口过程中处理WM_TIMER消息。调用KillTimer时,使用SetTimer中指定的hWnd和id。最好使用#define定义timer的id,例如:
#define ID_TIMER 1
SetTimer(hWnd,ID_TIMER,1000,NULL) ;
KillTimer(hWnd,ID_TIMER) ;
方法二:调用SetTimer时指定窗口句柄hWnd,nIDEvent中指定计时器ID,lpTimerFunc参数不为NULL而指定为TimerProc函数的指针。这种方法使用TimerProc函数(名字可自定)处理WM_TIMER消息:
VOID CALLBACK TimerProc ( HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
 //处理WM_TIMER讯息
}
TimerProc的参数hwnd是在调用SetTimer时指定的窗口句柄。Windows只把WM_TIMER消息送给TimerProc,因此消息参数总是等于WM_TIMER。iTimerID值是计时器ID,dwTimer值是与从GetTickCount函数的返回值相容的值。这是自Windows启动后所经过的毫秒数。使用这种方法时,相关函数调用的形式为:
SetTimer(hWnd,ID_TIMER,1000,TimerProc) ;
KillTimer(hWnd,ID_TIMER) ;
方法三:调用SetTimer时不指定窗口句柄(为NULL),iTimerID参数自然被忽略,lpTimerFunc不为NULL而指定为TimerProc的指针。正如上面SetTimer的讨论中所说的,此时SetTimer的返回值正是新建立的计时器的ID,需将这个ID保存以供KillTimer销毁计时器时所用。当然,KillTimer的hWnd参数也置为NULL。这种方法同样用TimerProc处理WM_TIMER消息
UINT_PTR iTimerID ;
iTimerID = SetTimer(NULL,0,1000,TimerProc) ;
KillTimer(NULL,iTimerID) ;
使用这种方法的好处是不必自己指定计时器ID,这样就不必担心用错ID。
(4)、使用多个计时器
使用多个计时器只要在建立计时器时指定不同的ID。比如用上面所述方法一时的情况:
#define TIMER_SEC 1
#define TIMER_MIN 2

然后使用两个SetTimer来设定两个计时器:
SetTimer (hwnd, TIMER_SEC, 1000, NULL) ;
SetTimer (hwnd, TIMER_MIN, 60000, NULL) ;

WM_TIMER
的处理如下所示:
case WM_TIMER:
 switch (wParam)
 {
  case TIMER_SEC:
   //每秒一次的处理
   break ;
  case TIMER_MIN:
   //每分钟一次的处理
   break ;
 }
 return 0 ;
 

VC++中的计时器及多媒体高精度计时器

Windows计时器是一个非常有用的编程元素,而且计时器的使用非常简单,我们只需要一个时间间隔参数来调用SetTimer函数设置和启动计时器,通过WM_TIMER消息的响应函数进行计时器控制,调用Ki...
  • margin1988
  • margin1988
  • 2015年01月05日 14:44
  • 1508

计时器---倒计时功能的实现

问题的实现描述:首先设置倒计时的时间,通过UIDatePicker来制定倒计时的时长,点击“确定”按钮,跳转到倒计时页面,同时将UIDatePicker定义的时间传到新push的页面的上方label位...
  • qq_27364431
  • qq_27364431
  • 2015年06月08日 16:23
  • 984

VC计时器的一个使用心得

                                                                               朱金灿 最近使用VC的计时器。计时器一般是...
  • clever101
  • clever101
  • 2008年02月24日 00:17
  • 6127

VC++中使用普通计时器和多媒体高精度计时器

  • 2015年01月05日 14:30
  • 131KB
  • 下载

c++设计一个计时器(能够暂停,重新开始,继续)的功能。写的不好,仅供参考!

完全模拟计时器实现(时间精确到 秒 即可) 功能要求: 1.计时器的开始功能 例如:键盘按键a 开始计时。 2.计时器的暂停功能 例如:键盘按键空格键 计时暂停 3.计时器的停止功能 例如...
  • tian_123456789
  • tian_123456789
  • 2016年03月27日 08:59
  • 1927

一个简陋的自定义用线程Thread实现的计时器Timer,可以增加定时时间

原来用的Timer(java.util.Timer),后来需要中途增加延迟时间,Timer不支持。自己写了个简陋的,应该够用。类如下:public class ExTimer extends Thre...
  • qq_25806863
  • qq_25806863
  • 2017年03月03日 17:06
  • 1215

VC++中计时器timer的运用

1、MFC中的计时原理: 当你需要每隔一段时间执行一件事的的时候就需要使用SetTimer()函数了。 让我们先来看看SetTimer函数的原型:     UINT SetTimer(UINT n...
  • jmxiaocai
  • jmxiaocai
  • 2012年02月02日 09:46
  • 4160

VC ++ MFC 中用 Ontimer 编写的计时器

  • 2010年04月29日 11:08
  • 41KB
  • 下载

关于计时的相关知识点

此篇文章包括多个知识点,涉及到timer,timerTask,countdowntimer,handler及alermmanager 等相关知识点...
  • android_yck
  • android_yck
  • 2016年11月07日 22:12
  • 203

用c++编写计时器的步骤及其函数代码

用c++语言编写计时器 编写过程中用到的函数: 一、void gotoxy(int x,int y)和void hoidden()函数: 1:所需的头文件include include 2:功能:将控...
  • qq_34118845
  • qq_34118845
  • 2016年03月26日 17:44
  • 969
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VC++中计时器的运用
举报原因:
原因补充:

(最多只允许输入30个字)