Visual C++——定时器(计时器)SetTimer函数

Visual C++——定时器(计时器)SetTimer函数本文详细介绍了 Windows 系统中 SetTimer 和 KillTimer 函数的使用方法 包括基本概念 API 函数原型 参数意义 WM TIMER 消息处理及常见问题解答 探讨了计时器的精确性和 WM TIMER 消息的响应问题

大家好,欢迎来到IT知识分享网。

基本概念 

SetTimer函数用于创建一个计时器

KillTimer函数用于销毁一个计时器。

计时器属于系统资源,使用完应及时销毁。 

API 

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相同的tiemr 

uElapse是以毫秒指定的计时间隔值,范围为1毫秒到4,294,967,295毫秒(将近50天),这个值指示Windows每隔多久时间给程序发送WM_TIMER消息。 

lpTimerFunc是一个回调函数的指针,俗称TimerFunc;如果lpTimerFunc为NULL,系统将向应用程序队列发送WM_TIMER消息;如果lpTimerFunc指定了一个值,DefWindowProc将在处理WM_TIMER消息时调用这个lpTimerFunc所指向的回调函数,因此即使使用TimerProc代替处理WM_TIMER也需要向窗口分发消息。 

返回值:如果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消息) 

关于WM_TIMER消息 

wParam为计时器的ID;

如果需要设定多个计时器,那么对每个计时器都使用不同的计时器ID。

wParam的值将随传递到窗口过程中的WM_TIMER消息的不同而不同。 

使用方法

如果在程序的整个执行过程中使用计时器,一般在处理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。 

使用多个计时器 

使用多个计时器只要在建立计时器时指定不同的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 ; 

改变计时器的时间间隔 

常见问题 

计时器精确吗? 

计时器并不精确。有两个原因: 

即使忽略这几个毫秒的差别,计时器仍然不精确。请看原因二: 

由以上两点,你不能通过在处理WM_TIMER时一秒一秒计数的方法来计时。如果要实现一个时钟程序,可以使用系统的时间函数如GetLocalTime ,而在时钟程序中,计时器的作用是定时调用GetLocalTime获得新的时间并刷新时钟画面,当然这个刷新的间隔要等于或小于1秒。

 WM_TIMER消息无法响应

https://bbs.csdn.net/topics/?list=lz

参考文章

http://www.studynew.com/study/vc/2004082519380331684.html

http://blog.sina.com.cn/s/blog_5a6f39cf010148xy.html

Visual C++——定时器(计时器)SetTimer函数

Visual C++——定时器(计时器)SetTimer函数

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/121952.html

(0)
上一篇 2025-10-20 13:45
下一篇 2025-10-20 14:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信