使用多个计时器只要在建立计时器时指定不同的
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 ;
改变计时器的时间间隔
如果想将一个已经存在的计时器设定为不同的时间间隔,可以简单地用不同的时间值再次调用
SetTimer
。
计时器精确吗?
计时器并不精确。有两个原因:
原因一:
Windows 计时器是硬件和 ROM BIOS 架构下之计时器一种相对简单的扩充。回到 Windows 以前的 MS-
DOS 程序写作环境下,应用程式能够通过拦截者称为 timer tick 的 BIOS 中断来实现时钟或计时器。一些为
MS-DOS 编写的程序自己拦截这个硬件中断以实现时钟和计时器。这些中断每 54.915 毫秒产生一次,或者大约每
秒
18.2 次。这是原始的 IBM PC 的微处理器频率值 4.772720 MHz 被 218 所除而得出的结果。在 Windows 98
中,计时器与其下的
PC 计时器一样具有 55 毫秒的解析度。在 Microsoft Windows NT 中,计时器的解析度为
10 毫秒。Windows 应用程式不能以高于这些解析度的频率(在 Windows 98 下,每秒 18.2 次,在 Windows
NT 下,每秒大约 100 次)接收 WM_TIMER 消息。在 SetTimer 中指定的时间间隔总是截尾后 tick 数的整数倍。
例如,
1000 毫秒的间隔除以 54.925 毫秒,得到 18.207 个 tick,截尾后是 18 个 tick,它实际上是 989 毫秒。
对每个小于
55 毫秒的间隔,每个 tick 都会产生一个 WM_TIMER
消息。
可见,计时器并不能严格按照指定的时间间隔发送
WM_TIMER
消息,它总要相差那么几毫秒。
即使忽略这几个毫秒的差别,计时器仍然不精确。请看原因二:
WM_TIMER 消息放在正常的消息队列之中,和其他消息排列在一起,因此,如果在 SetTimer 中指定间隔为 1000
毫秒,那么不能保证程序每
1000 毫秒或者 989 毫秒就会收到一个 WM_TIMER 消息。如果其他程序的执行事件超
过一秒,在此期间内,您的程式将收不到任何
WM_TIMER
讯息。事实上,
Windows 对 WM_TIMER 消息的处理非
常类似于对
WM_PAINT 消息的处理,这两个消息都是低优先级的,程序只有在消息队列中没有其他消息时才接收
它们。
WM_TIMER 还在另一方面和 WM_PAINT 相似:Windows 不能持续向消息队列中放入多个 WM_TIMER 讯息,而是将
多余的
WM_TIMER 消息组合成一个消息。因此,应用程序不会一次收到多个这样的消息,尽管可能在短时间内得
到两个
WM_TIMER 消息。应用程序不能确定这种处理方式所导致的 WM_TIMER
消息「遗漏」的数目。
可见,
WM_TIMER 消息并不能及时被应用程序所处理,WM_TIMER 在消息队列中的延误可能就不能用毫秒来计算
了。
由以上两点,你不能通过在处理
WM_TIMER 时一秒一秒计数的方法来计时。如果要实现一个时钟程序,可以使用
系统的时间函数如
GetLocalTime ,而在时钟程序中,计时器的作用是定时调用 GetLocalTime 获得新的时间
并刷新时钟画面,当然这个刷新的间隔要等于或小于
1 秒。