WM_TIMER消息的使用方法

WM_TIMER消息的使用方法
WM_TIMER消息的使用方法

银监统计类考试侧重金融监管相关的统计学理论和实务,包括统计学基础、宏观经济学、金融学、财务管理、会计学、金融风险管理、管理信息系统等;

S e t T i m e r函数用于创建一个计时器,K i l l T i m e r函数用于销毁一个计时器。计时器属于系统资源,使用完应及时销毁。

S e t T i m e r的函数原型如下:

U I N T_P T R S e t T i m e r(H W N D h W n d,U I N T_P T R n I D E v e n t,U I N T u E l a p s e, T I M E R P R O C l p T i m e r F u n c);

其中

h W n d是和t i m e r关联的窗口句柄,此窗口必须为调用S e t T i m e r的线程所有;如果h W n d为N U L L,没有窗口和t i m e r相关联并且n I D E v e n t参数被忽略

n I D E v e n t是t i m e r的标识,为非零值;如果h W n d为N U L L则被忽略;如果h W n d 非N U L L而且与t i m e r相关联的窗口已经存在一个为此标识的t i m e r,则此次S e t T i m e r调用将用新的t i m e r代替原来的t i m e r。t i m e r标识和窗口相关,两个不同的窗口可以拥有n I D E v e n t相同的t i e m r

u E l a p s e是以毫秒指定的计时间隔值,范围为1毫秒到4,294,967,295毫秒(将近50天),这个值指示W i n d o w s每隔多久时间给程序发送W M_T I M E R消息。l p T i m e r F u n c是一个回调函数的指针,俗称T i m e r F u n c;如果l p T i m e r F u n c为N U L L,系统将向应用程序队列发送W M_T I M E R消息;如果l p T i m e r F u n c指定了一个值,D e f W i n d o w P r o c将在处理W M_T I M E R消息时调用这个l p T i m e r F u n c 所指向的回调函数,因此即使使用T i m e r P r o c代替处理W M_T I M E R也需要向窗口分发消息。

关于S e t T i m e r的返回值:如果h W n d为N U L L,返回值为新建立的t i m e r的I D,如果h W n d非N U L L,返回一个非0整数,如果S e t T i m e r调用失败则返回0

K i l l T i m e r的函数原型为:B O O L K i l l T i m e r(H W N D h W n d,U I N T_P T R u I D E v e n t);参数意义同S e t T i m e r。

关于K i l l T i m e r对消息队列中剩余未处理的W M_T I M E R消息的影响,M S D N和P r o g r a m m i n g W i n d o w s上的说法完全相反。M S D N的说法很干脆:T h e K i l l T i m e r f u n c t i o n d o e s n o t r e m o v e W M_T I M E R m e s s a g e s a l r e a d y p o s t e d t o t h e m e s s a g e q u e u e.而p e t z o l d则说T h e K i l l T i m e r c a l l p u r g e s t h e m e s s a g e q u e u e o f a n y p e n d i n g W M_T I M E R m e s s a g e s.Y o u r p r o g r a m w i l l n e v e r r e c e i v e a s t r a y W M_T I M E R m e s s a g e f o l l o w i n g a K i l l T i m e r c a l l.(K i l l T i m e r消除消息队列中任何未处理的W M_T I M E R消息,调用K i l l T i m e r后你的程序永远不会收到一条“漂泊游荡”的W M_T I M E R消息)

关于W M_T I M E R消息

w P a r a m为计时器的I D;如果需要设定多个计时器,那么对每个计时器都使用不同的计时器I D。w P a r a m的值将随传递到窗口过程中的W M_T I M E R消息的不同而不同。

l P a r a m为指向T i m e r P r o c的指针,如果调用S e t T i m e r时没有指定T i m e r P r o c(参数值为N U L L),则l P a r a m为0(即N U L L)。

可以通过在窗口过程中提供一个W M_T I M E R c a s e处理这个消息,或者,默认窗口过程会调用S e t T i m e r中指定的T i m e r P r o c来处理W M_T I M E R消息

使用计时器的三种方法

如果在程序的整个执行过程中使用计时器,一般在处理W M_C R E A T E消息时或W i n M a i n中消息循环前调用S e t T i m e r,在处理W M_D E S T R O Y消息时或在W i n M a i n中消息循环后r e t u r n前调用K i l l T i m e r。根据S e t T i m e r中的参数不同,有三种方法使用计时器。

方法一:调用S e t T i m e r时指定窗口句柄h W n d,n I D E v e n t中指定计时器I D,

将l p T i m e r F u n c置N U L L从而不使用T i m e r P r o c;在窗口过程中处理W M_T I M E R 消息。调用K i l l T i m e r时,使用S e t T i m e r中指定的h W n d和i d。最好使用#d e f i n e 定义t i m e r的i d,例如:

#d e f i n e I D_T I M E R1

S e t T i m e r(h W n d,I D_T I M E R,1000,N U L L);

K i l l T i m e r(h W n d,I D_T I M E R);

方法二:调用S e t T i m e r时指定窗口句柄h W n d,n I D E v e n t中指定计时器I D,l p T i m e r F u n c参数不为N U L L而指定为T i m e r P r o c函数的指针。这种方法使用T i m e r P r o c函数(名字可自定)处理W M_T I M E R消息:

V O I D C A L L B A C K T i m e r P r o c(H W N D h w n d,U I N T m e s s a g e,U I N T i T i m e r I D, D W O R D d w T i m e)

{

//处理W M_T I M E R讯息

}

T i m e r P r o c的参数h w n d是在调用S e t T i m e r时指定的窗口句柄。W i n d o w s只把W M_T I M E R消息送给T i m e r P r o c,因此消息参数总是等于W M_T I M E R。

i T i m e r I D值是计时器I D,d w T i m e r值是与从G e t T i c k C o u n t函数的返回值相容的值。这是自W i n d o w s启动后所经过的毫秒数。使用这种方法时,相关函数调用的形式为:

S e t T i m e r(h W n d,I D_T I M E R,1000,T i m e r P r o c);

K i l l T i m e r(h W n d,I D_T I M E R);

方法三:调用S e t T i m e r时不指定窗口句柄(为N U L L),i T i m e r I D参数自然被忽略,l p T i m e r F u n c不为N U L L而指定为T i m e r P r o c的指针。正如上面S e t T i m e r 的讨论中所说的,此时S e t T i m e r的返回值正是新建立的计时器的I D,需将这个

I D保存以供K i l l T i m e r销毁计时器时所用。当然,K i l l T i m e r的h W n d参数也置为N U L L。这种方法同样用T i m e r P r o c处理W M_T I M E R消息。

U I N T_P T R i T i m e r I D;

i T i m e r I D=S e t T i m e r(N U L L,0,1000,T i m e r P r o c);

K i l l T i m e r(N U L L,i T i m e r I D);

使用这种方法的好处是不必自己指定计时器I D,这样就不必担心用错I D。

使用多个计时器

使用多个计时器只要在建立计时器时指定不同的I D。比如用上面所述方法一时的情况:

#d e f i n e T I M E R_S E C1

#d e f i n e T I M E R_M I N2

然后使用两个S e t T i m e r来设定两个计时器:

S e t T i m e r(h w n d,T I M E R_S E C,1000,N U L L);

S e t T i m e r(h w n d,T I M E R_M I N,60000,N U L L);

W M_T I M E R的处理如下所示:

c a s e W M_T I M E R:

s w i t c h(w P a r a m)

{

c a s e T I M E R_S E C:

//每秒一次的处理

b r e a k;

c a s e T I M E R_M I N:

//每分钟一次的处理

b r e a k;

}

r e t u r n0;

改变计时器的时间间隔

如果想将一个已经存在的计时器设定为不同的时间间隔,可以简单地用不同的时间值再次调用S e t T i m e r。

计时器精确吗?

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

原因一:W i n d o w s计时器是硬件和R O M B I O S架构下之计时器一种相对简单的扩充。回到W i n d o w s以前的M S-D O S程序写作环境下,应用程式能够通过拦截者称为t i m e r t i c k的B I O S中断来实现时钟或计时器。一些为M S-D O S编写的程序自己拦截这个硬件中断以实现时钟和计时器。这些中断每54.915毫秒产生一次,或者大约每秒18.2次。这是原始的I B M P C的微处理器频率值 4.772720 M H z 被218所除而得出的结果。在W i n d o w s 98中,计时器与其下的P C计时器一样具有55毫秒的解析度。在M i c r o s o f t W i n d o w s N T中,计时器的解析度为10毫秒。W i n d o w s应用程式不能以高于这些解析度的频率(在W i n d o w s98下,每秒18.2次,在W i n d o w s N T下,每秒大约100次)接收W M_T I M E R消息。在S e t T i m e r中指定的时间间隔总是截尾后t i c k数的整数倍。例如,1000毫秒的间隔除以54.925毫秒,得到18.207个t i c k,截尾后是18个t i c k,它实际上是989毫秒。对每个小于55毫秒的间隔,每个t i c k都会产生一个W M_T I M E R消息。可见,计时器并不能严格按照指定的时间间隔发送W M_T I M E R消息,它总要相差那么几毫秒。

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

W M_T I M E R消息放在正常的消息队列之中,和其他消息排列在一起,因此,如

果在S e t T i m e r中指定间隔为1000毫秒,那么不能保证程序每1000毫秒或者989毫秒就会收到一个W M_T I M E R消息。如果其他程序的执行事件超过一秒,在此期间内,您的程式将收不到任何W M_T I M E R讯息。事实上,W i n d o w s对W M_T I M E R消息的处理非常类似于对W M_P A I N T消息的处理,这两个消息都是低优先级的,程序只有在消息队列中没有其他消息时才接收它们。

W M_T I M E R还在另一方面和W M_P A I N T相似:W i n d o w s不能持续向消息队列中放入多个W M_T I M E R讯息,而是将多余的W M_T I M E R消息组合成一个消息。因此,应用程序不会一次收到多个这样的消息,尽管可能在短时间内得到两个W M_T I M E R消息。应用程序不能确定这种处理方式所导致的W M_T I M E R消息「遗漏」的数目。

可见,W M_T I M E R消息并不能及时被应用程序所处理,W M_T I M E R在消息队列中的延误可能就不能用毫秒来计算了。

由以上两点,你不能通过在处理W M_T I M E R时一秒一秒计数的方法来计时。如果要实现一个时钟程序,可以使用系统的时间函数如G e t L o c a l T i m e,而在时钟程序中,计时器的作用是定时调用G e t L o c a l T i m e获得新的时间并刷新时钟画面,当然这个刷新的间隔要等于或小于1秒。

相关主题
相关文档
最新文档