SetTimer,settime怎么用
EtTimer函数用于创建一个定时器,KillTimer函数用于销毁一个定时器。定时器属于系统资源,使用后应及时销毁。
SetTimer的功能原型如下:
UINT_PTR SetTimer( HWND hWnd,UINT_PTR nIDEvent,UINT uElapse,timer proc lpTimerFunc);
在…之中
HWnd是timer关联的窗口句柄,必须由调用SetTimer的线程拥有;如果hWnd为空,则没有窗口与timer相关联,并且忽略nIDEvent参数。
NIDEvent是定时器的标识符,为非零值;如果hWnd为空,则忽略它;如果hWnd不为空,并且与timer相关联的窗口已经有一个具有该标识符的timer,那么这个Settimer调用将用一个新的timer替换原来的timer。定时器标识与窗口相关,两个不同的窗口可以有相同的nIDEvent的tiemr。
UElapse是以毫秒为单位指定的时间间隔值,范围从1毫秒到4,294,967,295毫秒(近50天)。此值表示Windows向程序发送WM_TIMER消息的频率。
Timerfunc是一个回调函数的指针,俗称timer func;如果lpTimerFunc为空,系统将向应用队列发送WM_TIMER消息;如果lpTimerFunc指定了一个值,DefWindowProc在处理WM_TIMER消息时会调用这个lpTimerFunc指向的回调函数,所以即使使用TimerProc而不是处理WM_TIMER,也需要将消息分发到窗口。
关于SetTimer的返回值:如果hWnd为空,返回值为新建立的定时器的ID,如果hWnd为非空,返回非零整数,如果Settimer调用失败,返回0。
KillTimer的函数原型是:bool kill timer (hwnd hwnd,uint _ ptruid事件);参数与SetTimer的含义相同。
关于KillTimer对消息队列中剩余未处理的WM_TIMER消息的影响,MSDN和编程窗口上的说法完全相反。MSDN的声明非常简单:kill timer函数不会删除已经发布到消息队列中的WM _ timer消息。petzold说KillTimer调用清除了messa。任何未决WM _ timer消息的Ge。在kill timer调用之后,您的程序将永远不会收到straywm _ timer消息。(kill timer清除消息队列中任何未处理的w。M_TIMER消息,在调用KillTimer之后,你的程序将永远不会收到一个“游荡”的WM_TIMER消息)
关于WM_TIMER消息
WParam是计时器的id;如果需要设置多个定时器,请为每个定时器使用不同的定时器ID。wParam的值将随着传递给窗口的WM_TIMER消息而变化。
lParam是指向TimerProc的指针,如果调用SetTimer时没有指定TimerProc(参数值为NULL),则LParam为0(即NULL)。
您可以通过在窗口过程中提供WM_TIMER case来处理此消息,或者默认窗口过程将调用SetTimer中指定的TimerProc来处理WM_TIMER消息。
使用定时器的三种方式
如果在程序执行的全过程中使用定时器,一般在WinMain中处理WM_CREATE消息时或消息循环前调用SetTimer,在WinMain中处理WM_DESTROY消息时或消息循环后返回前调用KillTimer。根据SetTimer中的参数,有三种使用定时器的方法。
方法一:调用SetTimer时,指定窗口句柄hWnd,在nIDEvent中指定timer ID,将lpTimerFunc设置为NULL,以便不使用TimerProc;WM_TIMER消息在窗口过程中处理。调用KillTimer时使用SetTimer中指定的hWnd和id。最好使用#define来定义定时器的id,例如:
#定义ID_TIMER 1
SetTimer(hWnd,ID_TIMER,1000,NULL);
KillTimer(hWnd,ID _ TIMER);
方法二:调用SetTimer时指定窗口句柄hWnd,在nIDEvent中指定timer ID,lpTimerFunc参数不为NULL但指定为TimerProc函数的指针。该方法使用TimerProc函数(名字可以自定义)处理WM_TIMER消息:
VOID回调TimerProc ( HWND hwnd,UINT message,UINT iTimerID,DWORD dwTime)
{
//处理WM_TIMER消息
}
TimerProc的参数hwnd是调用SetTimer时指定的窗口句柄。Windows只向TimerProc发送WM_TIMER消息,所以消息参数始终等于WM_TIMER。ITimerID值是计时器ID,dwTimer值是与GetTickCount函数的返回值兼容的值。这是自Windows启动以来的毫秒数。使用此方法时,相关函数调用的形式如下:
SetTimer(hWnd,ID_TIMER,1000,TIMER proc);
KillTimer(hWnd,ID _ TIMER);
方法三:调用SetTimer时,不指定窗口句柄(NULL),自然忽略iTimerID参数,lpTimerFunc不为NULL而是指定为TimerProc的指针。上面对SetTimer的讨论中提到过,此时SetTimer的返回值只是新建立的定时器的ID,需要保存下来供KillTimer销毁定时器。当然KillTimer的hWnd参数也设置为NULL。该方法还使用TimerProc来处理WM_TIMER消息。
UINT _ PTR iTimerID
iTimerID=SetTimer(NULL,0,1000,timer proc);
KillTimer(NULL,it imerid);
使用这种方法的好处是,您不必自己指定计时器ID,因此您不必担心使用错误的ID。
使用多个计时器
只要在创建计时器时指定不同的id,就可以使用多个计时器。例如,当上述方法使用一段时间后:
#定义定时器_秒1
#定义TIMER_MIN 2
然后使用两个SetTimer来设置两个计时器:
SetTimer (hwnd,TIMER_SEC,1000,NULL);
SetTimer (hwnd,TIMER_MIN,60000,NULL);
WM_TIMER的处理如下:
案例WM_TIMER:
开关(wParam)
{
案例计时器_秒:
//每秒处理一次
打破;
案例计时器_分钟:
//每分钟处理一次
打破;
}
返回0;
更改计时器的时间间隔
如果您想将现有的计时器设置为不同的时间间隔,只需用不同的时间值再次调用SetTimer。
计时器不准确。有两个原因:
一个原因:Windows timer是timer在硬件和ROM BIOS架构上相对简单的扩展。回到以前Windows的MS-DOS编程环境,应用程序可以通过拦截BIOS中断调用timer tick来实现时钟或定时器。一些为MS-DOS编写的程序自己截取这个硬件中断来实现时钟和定时器。这些中断每54.915毫秒发生一次,即每秒大约18.2次。这是原始IBM PC微处理器频率值4.772720 MHz除以218的结果。在Windows 98中,计时器的分辨率与它下面的PC计时器一样,都是55毫秒。在Microsoft Windows NT中,计时器的分辨率为10ms。Windows应用程序无法以高于这些分辨率的频率接收WM_TIMER消息(在Windows 98下为每秒18.2次,在Windows NT下约为每秒100次)。SetTimer中指定的时间间隔总是截断后刻度数的整数倍。例如,1000毫秒的间隔除以54.925毫秒得到18.207个刻度。截断后,有18个刻度,实际上是989毫秒。每个tick在小于55毫秒的时间间隔内生成一个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秒。