第八章 计时器

来源:互联网 发布:淘宝上有hm旗舰店吗 编辑:程序博客网 时间:2024/05/20 20:56

 

计时器的三种方法

方法一

SetTimer 函数:它导致Windows将WM_TIMER消息发送到应用程序的窗口过程。

SetTimer(hwnd, iTimerID, uiMsecInterval, NULL);

第一个参数:窗口句柄,它指向接收MM_TIMER消息的窗口过程

第二个参数:一个计时器ID,它不能为0。
第三个参数:一个32位无符号整数,它指定以毫秒为单位的时间间隔。

你可以在任何时刻停止WM_TIMER消息(甚至当处理WM_TIMER消息时),使用下面函数:

KillTimer(hwnd, ID);//第二个参数:相应的SetTimer使用的计时器ID

当窗口过程接收到WM_TIMER消息时,wParam等于计时器的ID,lParam是0。

使用多个计时器时,则每个计时器使用不同的ID。wParam的值将帮助区分送到窗口过程的WM_TIMER消息。

通常使用#define 定义不同的计时器ID。

#define TIMER_SEC 1#define TIMER_MIN 2

调用SetTimer函数设置两个计时器:

SetTimer(hwnd, TIMER_SEC, 1000, NULL);SetTimer(hwnd, TIMER_MIN, 6000,NULL);

WM_TIMER消息的处理逻辑如下:

case WM_TIMER:switch(wParam){   case  TIMER_SEC:               //每秒钟一次的处理break;  case TIMER_MIN:             //每一分钟一次的处理break;}return 0;

实例程序代码:

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){HDChdc;PAINTSTRUCTps;HBRUSH  hBrush;RECT rect;static BOOL fFlipFlop = FALSE;switch(message){case WM_CREATE:SetTimer(hwnd, ID_TIMER, 1000, NULL);   //ID_TIMER  1return 0;case WM_TIMER:fFlipFlop = !fFlipFlop;InvalidateRect(hwnd, NULL, FALSE);return 0;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);GetClientRect(hwnd, &rect);hBrush = CreateSolidBrush(fFlipFlop ? RGB(255,0, 0) : RGB(0, 0, 255));FillRect(hdc, &rect,hBrush);EndPaint(hwnd,&ps);DeleteObject(hBrush);return 0;case WM_DESTROY:KillTimer(hwnd, ID_TIMER);PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);}

方法二

第一种方法是把WM_TIMER消息送给正常的窗口过程。

第二种方法则让你指挥Windows把计时器消息发送到程序中的另一个函数。

收到计时器消息的函数被称为“回调”函数。这是程序中被Windows调用的函数。你告诉Windows这个函数的地址,Windows以后就会调用这个函数。

这听上去很熟悉,其实一个程序的窗口过程就属于回调函数的一种。注册窗口类时告诉Windows你的窗口过程的地址后,只要Windows向你的程序发送消息,就会自动调用此函数。(第十一章 CreateDialog和DialogBox都使用回调函数处理对话框消息)

计时器的回调函数并不返回数值给Windows。

回调函数:TimerProc,这个函数只处理WM_TIMER消息

VOID CALLBACK TimerProc (HWND   hwnd, UINT   message, UINT   iTimerID, DWORD   dwTime)//iTimerID值是计时器的ID,dwTime是从GetTickCount函数返回的值,它记录了自从Windows启动到现在所逝去的毫秒数。{   //  处理WM_TIMER消息  }

使用回调函数处理WM_TIMER消息时,SetTimer函数的第四个参数必须设定为回调函数的地址:

SetTimer(hwnd, iTimerID, uiMsecInterval, TimerProc);

 程序代码实例:

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){HDChdc;PAINTSTRUCTps;switch(message){case WM_CREATE:SetTimer(hwnd, ID_TIMER, 1000, TimerProc);//ID_TIMER 1return 0;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);EndPaint(hwnd,&ps);return 0;case WM_DESTROY:KillTimer(hwnd, ID_TIMER);PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);}VOID CALLBACK TimerProc(HWND hWnd, UINT TimerMsg, UINT iTimerID, DWORD dwTime){static BOOL fFlipFlop =  FALSE;HBRUSHhBrush;HDChdc;RECTrect;fFlipFlop = !fFlipFlop;GetClientRect(hWnd, &rect);hdc = GetDC(hWnd);hBrush = CreateSolidBrush(fFlipFlop ? RGB(255,0,0) : RGB(0,255,0));FillRect(hdc, &rect, hBrush);ReleaseDC(hWnd,hdc);DeleteObject(hBrush);}

方法三

与第二种相似,但是SetTimer的hwnd参数被设置为NULL,而且第二参数被忽略了(正常情况下是计时器的ID)。此外,这个函数会返回计时器的ID。

iTimerID = SetTimer(NULL, 0, wMsecInterval, TimerProc);  //返回的iTimerID为 0 ,表示没有可用的计时器。

同样的KillTimer的第一个参数也必须是NULL。计时器的ID必须是从SetTimer返回的值:

KillTimer(NULL, iTimerID);

传给TimerProc计时器函数的hwnd参数也将是NULL。一般这种设置计时器的方法很少用到。如果在程序中,需要在不同的时刻调用很多次SetTimer,但又不想记录哪些计时器ID已经被使用过,那么这种方法可能会派上用场。

下面是关天计时器的程序实例:

明个更
0 0
原创粉丝点击