1 WM_Timer消息的产生:
windows本身处理硬件中断,对于应用程序的定时器,windows存储一个每次硬件timer_tick减少的计时数,当这个数减少到0的时候,windows会在应用程序的消息对列中放一个WM_Timer的消息,同时将timer_tick恢复到原值。由于WM_Timer消息是在消息队列中,所以其类似鼠标和键盘,不会中断应用程序的执行。
2 定时器的准确性:
windows定时器是PC硬件和ROM BIOS架构下对定时器的一种相当简单的扩充。所以它的分辨率是有固定值的,在Windows98中,时钟频率是每秒18.2次,windowsNT(windows New Technology,从Windows NT 3.1到现在的win8都是windowsNT)是100次每秒,所以在SetTimer中设置的时间nTime/deltaTime = timer_tick,deltaTime是指windows系统定时器的时间间隔(windowsNT,那就是10ms了)。
(1)从上面可以看出,timer_tick是个截尾的整数,并且当nTime<deltaTime的时候,timer_tick =0(此时每个tick都会触发WM_Timer消息),因此从此可以看出,定时器是不精确的。
(2)WM_TIMER是在消息队列中放着,它的优先级比较低,并且它类似WM_PAINT,一个消息队列中不会有多于一个的WM_TIMER消息,windows会将多余的WM_TIMER消息合成一个WM_TIMER消息,这样会造成计时的不准确性
(3)当消息队列中一个消息的处理时间大于计时器间隔的时候,那么在这一个计时间隔内,WM_TIMER消息也不会被处理,这样也会造成计时的不准确性。
3 WM_TIMER 消息的wParam和lParam:
wParam表示的是 timer Identifier(计时器标识符),lParam表示的是 timer callback(计时器回调函数)
4 高性能计数器:
常用函数如下:
windows本身处理硬件中断,对于应用程序的定时器,windows存储一个每次硬件timer_tick减少的计时数,当这个数减少到0的时候,windows会在应用程序的消息对列中放一个WM_Timer的消息,同时将timer_tick恢复到原值。由于WM_Timer消息是在消息队列中,所以其类似鼠标和键盘,不会中断应用程序的执行。
2 定时器的准确性:
windows定时器是PC硬件和ROM BIOS架构下对定时器的一种相当简单的扩充。所以它的分辨率是有固定值的,在Windows98中,时钟频率是每秒18.2次,windowsNT(windows New Technology,从Windows NT 3.1到现在的win8都是windowsNT)是100次每秒,所以在SetTimer中设置的时间nTime/deltaTime = timer_tick,deltaTime是指windows系统定时器的时间间隔(windowsNT,那就是10ms了)。
(1)从上面可以看出,timer_tick是个截尾的整数,并且当nTime<deltaTime的时候,timer_tick =0(此时每个tick都会触发WM_Timer消息),因此从此可以看出,定时器是不精确的。
(2)WM_TIMER是在消息队列中放着,它的优先级比较低,并且它类似WM_PAINT,一个消息队列中不会有多于一个的WM_TIMER消息,windows会将多余的WM_TIMER消息合成一个WM_TIMER消息,这样会造成计时的不准确性
(3)当消息队列中一个消息的处理时间大于计时器间隔的时候,那么在这一个计时间隔内,WM_TIMER消息也不会被处理,这样也会造成计时的不准确性。
3 WM_TIMER 消息的wParam和lParam:
wParam表示的是 timer Identifier(计时器标识符),lParam表示的是 timer callback(计时器回调函数)
4 高性能计数器:
常用函数如下:
DWORD GetTickCount(void); //一个计时的函数,返回的从操作系统打开到目前经历的时间,单位是ms
BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount );//查询当前计数值
BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency );//查询计数频率,单位是Hz
实例代码如下:#include <Windows.h>
#include <stdio.h>
void main()
{
LARGE_INTEGER lgTime1 = {0};
LARGE_INTEGER lgTime2 = {0};
LARGE_INTEGER lgFrequ = {0};
BOOL bl;
bl = QueryPerformanceFrequency(&lgFrequ);
bl = QueryPerformanceCounter(&lgTime1);
for (int i=0;i<1000000000;i++)
{
;
;
;
}
bl = QueryPerformanceCounter(&lgTime2);
long long time =( ((lgTime2.QuadPart - lgTime1.QuadPart) * 1000)/lgFrequ.QuadPart);
printf("size of long long is:%d\n",sizeof(long long int));
printf("time passed %lld ms\n",time);
}
5 关于定时器主要用三种用法:
(1)首先看定时器的函数
UINT_PTR SetTimer(HWND hwnd,UINT_PTR nIDEvent, UINT uElaspse,TIMERPROC lpTimerFunc);
参数:
hwnd:毫无疑问,就是指的哪个窗口设置定时器
nIDEvent:就是定时器的标号,标识这个定时器和其他的定时器的区别
uElapse:定时器每触发一次的时间间隔,在windows中最小值是1ms。
lpTimerFunc:定时器触发时调用的回调函数。
(2)用法1:
lpTimerFunc=NULL,此时定时器触发时相应窗口过程函数中的WM_TIMER消息
SetTimer(hwnd,nTimerID,1000,NULL);
KillTimer(hwnd,nTimerID);
(3)用法2:
lpTimerFunc为指定的回调函数,如TimerFunc
(4)用法3:
当hwnd不为NULL时,SetTimer(hwnd,nIDTimer,uElapse,TimerFunc)返回的值等于nIDTimer;
当hwnd=NULL,nIDTimer会被忽略,函数返回的值是不为0的整数值,并以此数为定时器的标志。切记此时传到TimerFunc(……)函数中的hwnd也是为NULL,所以此时如果打算用之前的窗口hwnd画图的话就会得不到预期的效果,因为获取DC时,得到的HWND为NULL,如此而已。很多人第一次在看《windows程序设计》将BEEPER2.C -- Timer Demo Program No. 2中的SetTimer(hwnd,nIDTimer,uElapse,TimerFunc);改为TimerID=SetTimer (NULL, 0, 1000, TimerProc) ;时会发现此时客户区不再显示颜色交替变化,原因就是就是在传入TimerFunc中的hwnd此时为NULL,那么当然不会显示颜色变换了。这个时候只需要把窗口注册时的hwnd这一局部变量重新变成全局变量g_hwnd,并在画图时将原来的hwnd变成g_hwnd 即可。
6 关于时间的一些函数,结构体:
SYSTEMTIME:时间结构体
该结构体含有64位无符号的文件的日期和时间,表示自1601年1月1日开始的100纳秒为单位的时间。
7 一个关于时区的信息的结构体:
lpTimerFunc为指定的回调函数,如TimerFunc
SetTimer(hwnd,nTimerID,1000,TimerFunc);
KillTimer(hwnd,nTimerID);
void CALLBACK TimerFunc(HWND hwnd,UINT msg,UINT nTimerID,DWORD dwTime);
这个时间回调函数是windows从程序中的代码中调用的,所以不应再有返回值。这个东西是我做过实验的,可以验证的。(4)用法3:
iTimerID=SetTimer(NULL,0,uElapse,TimerProc);
KillTimer(hwnd,iTimerID);//此时关闭定时器用的参数也是前面函数返回的iTimerID
小结:当hwnd不为NULL时,SetTimer(hwnd,nIDTimer,uElapse,TimerFunc)返回的值等于nIDTimer;
当hwnd=NULL,nIDTimer会被忽略,函数返回的值是不为0的整数值,并以此数为定时器的标志。切记此时传到TimerFunc(……)函数中的hwnd也是为NULL,所以此时如果打算用之前的窗口hwnd画图的话就会得不到预期的效果,因为获取DC时,得到的HWND为NULL,如此而已。很多人第一次在看《windows程序设计》将BEEPER2.C -- Timer Demo Program No. 2中的SetTimer(hwnd,nIDTimer,uElapse,TimerFunc);改为TimerID=SetTimer (NULL, 0, 1000, TimerProc) ;时会发现此时客户区不再显示颜色交替变化,原因就是就是在传入TimerFunc中的hwnd此时为NULL,那么当然不会显示颜色变换了。这个时候只需要把窗口注册时的hwnd这一局部变量重新变成全局变量g_hwnd,并在画图时将原来的hwnd变成g_hwnd 即可。
6 关于时间的一些函数,结构体:
SYSTEMTIME:时间结构体
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME;
//获取本地的日期和时间
void GetLocalTime( LPSYSTEMTIME lpSystemTime );
//获取系统日期和时间
void GetSystemTime( LPSYSTEMTIME lpSystemTime );
//设置本地时间
BOOL SetLocalTime( const SYSTEMTIME* lpSystemTime );
//设置系统时间
BOOL SetSystemTime( const SYSTEMTIME* lpSystemTime);
文件时间:typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
该结构体含有64位无符号的文件的日期和时间,表示自1601年1月1日开始的100纳秒为单位的时间。
7 一个关于时区的信息的结构体:
typedef struct _TIME_ZONE_INFORMATION {
LONG Bias; //UTC = local time + bias
WCHAR StandardName[32];
SYSTEMTIME StandardDate;
LONG StandardBias;
WCHAR DaylightName[32];
SYSTEMTIME DaylightDate;
LONG DaylightBias;
} TIME_ZONE_INFORMATION