第八章 计时器
来源:互联网 发布:淘宝上有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已经被使用过,那么这种方法可能会派上用场。
下面是关天计时器的程序实例:
明个更- 第八章 计时器
- 第八章 8-1 计时器
- 第八章 8-3 在状态报告上使用计时器
- 第八章、图像处理与动画制作——图像控件和计时器的应用
- 第十三章 3.计时器
- 第8章 计时器
- 第 8 章 计时器
- 第 8 章 计时器
- 第六章 计时器
- 计时器
- 计时器
- 计时器
- 计时器
- 计时器
- 计时器
- 计时器
- 计时器
- 计时器
- 过去,现在和未来
- 对system/bin目录下可执行文件重命名操作
- 深度学习之Auto Encoder
- LeetCode Sort List
- Robot Motion
- 第八章 计时器
- 使用filter过滤器实现用户登录验证
- C++ Vector 使用心得
- HDU 1418抱歉
- 学习中
- LeetCode之Merge Sorted Array
- Cmake 学习
- 算法第二周作业
- 黑马程序员-Ado的主要五大对象