Win32 计时器消息 - WM_TIMER,SetTimer
来源:互联网 发布:淘宝如何权重 编辑:程序博客网 时间:2024/05/18 08:36
注:以下内容为学习笔记,多数是从书本、资料中得来,只为加深印象,及日后参考。然而本人表达能力较差,写的不好。因非翻译、非转载,只好选原创,但多数乃摘抄,实为惭愧。但若能帮助一二访客,幸甚!
以下内容多数来自于《Windows程序设计》
1.计时器基础
Windows计时器是一种输入设备,每到一个指定的时间间隔,它都会周期性地发送WM_TIMER通知应用程序。
一些应用:多任务、保持更新进度报告(不断显式变化的信息)、实现定期自动存储、终止程序的演示版、控制运动速度、多媒体。
Windows应用程序是通过正常的消息队列来接收WM_TIMER消息,所以不用担心程序在处理其他任务时会被突然而来的WM_TIMER消息所“中断”。
WM_TIMER消息被放在正常的消息队列中,并和其他消息一起排队等候处理。因此并不能保证每隔指定时间就收到一个WM_TIMER消息。
WM_TIMER和WM_PAINT消息类似,都是低优先级的,只有当消息队列中没有其他消息时,程序才会收到它们。同样,应用程序也同时不会收到大量的WM_TIMER消息。因此不能通过WM_TIMER消息数来判定过去了多长时间。
2.使用计时器的方法
1)法1:
SetTimer(hwnd, 1, uiMsecInterval, NULL);KillTimer(hwnd, 1);
在 WM_TIMER消息中,wParam等于计时器的ID。
/*-------------------------------------- BEEPER1.C -- Timer Demo Program ver1--------------------------------------*/#include <windows.h>#include <stdlib.h>#define ID_TIMER1LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){static TCHAR szAppName[] = TEXT("Beeper1");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if (!RegisterClass (&wndclass)){MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);return 0 ;}hwnd = CreateWindow(szAppName, TEXT ("Beeper1 Timer Demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);ShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){HBRUSHhBrush;HDChdc;PAINTSTRUCTps;RECTrc;switch (message){case WM_CREATE:SetTimer(hwnd, ID_TIMER, 1000, NULL);return 0 ;case WM_TIMER:MessageBeep(-1);InvalidateRect(hwnd, NULL, FALSE);return 0;case WM_PAINT:hdc = BeginPaint (hwnd, &ps) ;GetClientRect(hwnd, &rc);hBrush = CreateSolidBrush(RGB(rand()%255, rand()%255, rand()%255));FillRect(hdc, &rc, hBrush);EndPaint (hwnd, &ps) ;return 0 ;case WM_DESTROY:KillTimer(hwnd, ID_TIMER);PostQuitMessage (0) ;return 0 ;}return DefWindowProc (hwnd, message, wParam, lParam) ;}
2)法2:
让Windows把计时器消息发送到程序中的另一个函数。
收到计时器消息的函数被称为“回调”函数。这是程序中被Windows调用的函数。回调函数必须定义为CALLBACK类型,因为Windows是从程序的代码空间以外调用这个函数的。送到回调函数的参数和从回调函数返回的数据是由该函数要实现的功能所决定的。当回调函数与计时器同时使用时,它的参数实际上与窗口过程的参数是一样的,只不过他们的定义不同。
VOID CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime){} SetTimer(hwnd, iTimerID, iMsecInterval, TimerProc);示例:
/*----------------------------------------------------------- BEEPER2.cpp -- Timer Demo Program ver1------------------------------------------------------------*/#include <windows.h>#include <stdlib.h>#define ID_TIMER1LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);VOIDCALLBACK TimerProc(HWND, UINT, UINT, DWORD);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){static TCHAR szAppName[] = TEXT("Beeper2");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if (!RegisterClass (&wndclass)){MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);return 0 ;}hwnd = CreateWindow(szAppName, TEXT ("Beeper2 Timer Demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);ShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){switch (message){case WM_CREATE:SetTimer(hwnd, ID_TIMER, 1000, TimerProc);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 message, UINT iTimerID, DWORD dwTime){HBRUSHhBrush;HDChdc;RECTrc;MessageBeep(-1);GetClientRect(hwnd, &rc);hdc= GetDC(hwnd);hBrush = CreateSolidBrush(RGB(rand()%255, rand()%255, rand()%255));FillRect(hdc, &rc, hBrush);ReleaseDC(hwnd, hdc);DeleteObject(hBrush);}
3)法3:
需要多次调用SetTimer,又不想记录哪些计时器ID已经被使用过,可以:
iTimerID = SetTimer(NULL, 0, wMsecInterval, TimerProc);KillTimer(NULL, iTimerID);
3.使用计时器作为时钟
1)数字时钟
/*----------------------------------------------------------- digClock.cpp -- Digital Clock------------------------------------------------------------*/#include <windows.h>#define ID_TIMER1LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){static TCHAR szAppName[] = TEXT("DigClock");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if (!RegisterClass (&wndclass)){MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);return 0 ;}hwnd = CreateWindow(szAppName, TEXT ("Digital Clock"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);ShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}void DisplayDigit(HDC hdc, int iNumber){static BOOLfSevenSegment[10][7] = {1, 1, 1, 0, 1, 1, 1, // 00, 0, 1, 0, 0, 1, 0, // 11, 0, 1, 1, 1, 0, 1, // 21, 0, 1, 1, 0, 1, 1, // 30, 1, 1, 1, 0, 1, 0, // 41, 1, 0, 1, 0, 1, 1, // 51, 1, 0, 1, 1, 1, 1, // 61, 0, 1, 0, 0, 1, 0, // 71, 1, 1, 1, 1, 1, 1, // 81, 1, 1, 1, 0, 1, 1 // 9};static POINT ptSegment [7][6] = {7, 6, 11, 2, 31, 2, 35, 6, 31, 10, 11, 10,6, 7, 10, 11, 10, 31, 6, 35, 2, 31, 2, 11, 36, 7, 40, 11, 40, 31, 36, 35, 32, 31, 32, 11,7, 36, 11, 32, 31, 32, 35, 36, 31, 40, 11, 40,6, 37, 10, 41, 10, 61, 6, 65, 2, 61, 2, 41, 36, 37, 40, 41, 40, 61, 36, 65, 32, 61, 32, 41,7, 66, 11, 62, 31, 62, 35, 66, 31, 70, 11, 70 }; int iSeg;for (iSeg = 0; iSeg < 7; iSeg++)if (fSevenSegment[iNumber][iSeg])Polygon(hdc, ptSegment[iSeg], 6);}void DisplayTwoDigits(HDC hdc, int iNumber, BOOL fSuppress){//if (!fSuppress || (iNumber / 10 != 0))DisplayDigit(hdc, iNumber / 10);OffsetWindowOrgEx(hdc, -42, 0, NULL);DisplayDigit(hdc, iNumber % 10);OffsetWindowOrgEx(hdc, -42, 0, NULL);}void DisplayColon(HDC hdc){POINT ptColon[2][4] = { 2, 21, 6, 17, 10, 21, 6, 25, 2, 51, 6, 47, 10, 51, 6, 55 };Polygon(hdc, ptColon[0], 4);Polygon(hdc, ptColon[1], 4);OffsetWindowOrgEx(hdc, -12, 0, NULL);}void DisplayTime(HDC hdc, BOOL f24Hour, BOOL fSuppress){SYSTEMTIME st;GetLocalTime(&st);if (f24Hour)DisplayTwoDigits(hdc, st.wHour, fSuppress);elseDisplayTwoDigits(hdc, (st.wHour %= 12) ? st.wHour : 12, fSuppress);DisplayColon(hdc);DisplayTwoDigits(hdc, st.wMinute, fSuppress);DisplayColon(hdc);DisplayTwoDigits(hdc, st.wSecond, fSuppress);}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){static BOOLf24Hour, fSuppress;static HBRUSHhBrushRed;static intcxClient, cyClient;HDChdc;PAINTSTRUCTps;TCHARszBuffer[2];switch (message){case WM_CREATE:hBrushRed = CreateSolidBrush(RGB(255, 0, 0));SetTimer(hwnd, ID_TIMER, 1000, NULL);// fall throughcase WM_SETTINGCHANGE:GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 2);f24Hour = (szBuffer[0] == '1');GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITLZERO, szBuffer, 2);fSuppress = (szBuffer[0] == '0');InvalidateRect(hwnd, NULL, TRUE);return 0;case WM_SIZE:cxClient = LOWORD(lParam);cyClient = HIWORD(lParam);return 0;case WM_TIMER:InvalidateRect(hwnd, NULL, TRUE);return 0;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);SetMapMode(hdc, MM_ISOTROPIC);SetWindowExtEx(hdc, 276, 72, NULL);SetViewportExtEx(hdc, cxClient, cyClient, NULL);SetWindowExtEx(hdc, 138, 36, NULL);SetViewportExtEx(hdc, cxClient/2, cyClient/2, NULL);SelectObject(hdc, GetStockObject(NULL_PEN));SelectObject(hdc, hBrushRed);DisplayTime(hdc, f24Hour, fSuppress);EndPaint(hwnd, &ps);return 0;case WM_DESTROY:KillTimer(hwnd, ID_TIMER);DeleteObject(hBrushRed);PostQuitMessage (0) ;return 0 ;}return DefWindowProc (hwnd, message, wParam, lParam) ;}
2)模拟时钟
/*----------------------------------------------------------- digClock.cpp -- Digital Clock------------------------------------------------------------*/#include <windows.h>#include <math.h>#define ID_TIMER1#define TWOPI(2*3.14159)LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){static TCHAR szAppName[] = TEXT("DigClock");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if (!RegisterClass (&wndclass)){MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);return 0 ;}hwnd = CreateWindow(szAppName, TEXT ("Digital Clock"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);ShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}void SetIsotropic(HDC hdc, int cxClient, int cyClient){SetMapMode(hdc, MM_ISOTROPIC);SetWindowExtEx(hdc, 1000, 1000, NULL);SetViewportExtEx(hdc, cxClient/2, -cyClient/2, NULL);SetViewportOrgEx(hdc, cxClient/2, cyClient/2, NULL);}void RotatePoint(POINT pt[], int iNum, int iAngle){inti;POINTptTemp;for (i = 0; i < iNum; i++){ptTemp.x = (int)( pt[i].x * cos(TWOPI*iAngle/360) + pt[i].y * sin(TWOPI*iAngle/360) );ptTemp.y = (int)( pt[i].y * cos(TWOPI*iAngle/360) + pt[i].x * sin(TWOPI*iAngle/360) );pt[i] = ptTemp;}}void DrawClock(HDC hdc){intiAngle;POINTpt[3];for (iAngle = 0; iAngle < 360; iAngle += 6){pt[0].x = 0;pt[0].y = 900;RotatePoint(pt, 1, iAngle);pt[2].x = pt[2].y = iAngle%5 ? 33 : 100;pt[0].x -= pt[2].x / 2;pt[0].y -= pt[2].y / 2;pt[1].x = pt[0].x + pt[2].x;pt[1].y = pt[0].y + pt[2].y;SelectObject(hdc, GetStockObject(BLACK_BRUSH));Ellipse(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);}}void DrawHands(HDC hdc, SYSTEMTIME* pst, BOOL fChange){static POINT pt[3][5] = { 0, -150, 100, 0, 0, 600, -100, 0, 0, -150,0, -200, 50, 0, 0, 800, -50, 0, 0, -200,0, 0, 0, 0, 0, 0, 0, 0, 0, 800 };inti, iAngle[3];POINTptTemp[3][5];iAngle[0] = (pst->wHour * 30) % 360 + pst->wMinute/2;iAngle[1] = pst->wMinute * 6;iAngle[2] = pst->wSecond * 6;memcpy(ptTemp, pt, sizeof(pt));for (i = fChange ? 0 : 2; i < 3; i++){RotatePoint(ptTemp[i], 5, iAngle[i]);Polyline(hdc, ptTemp[i], 5);}}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){static SYSTEMTIMEstPrevious;static intcxClient, cyClient;BOOLfChange;HDChdc;PAINTSTRUCTps;SYSTEMTIMEst;switch (message){case WM_CREATE:SetTimer(hwnd, ID_TIMER, 1000, NULL);GetLocalTime(&st);stPrevious = st;return 0;case WM_SIZE:cxClient = LOWORD(lParam);cyClient = HIWORD(lParam);return 0;case WM_TIMER:GetLocalTime(&st);fChange = st.wHour != stPrevious.wHour || st.wMinute!= stPrevious.wHour;hdc = GetDC(hwnd);SetIsotropic(hdc, cxClient, cyClient);SelectObject(hdc, GetStockObject(WHITE_PEN));DrawHands(hdc, &stPrevious, fChange);SelectObject(hdc, GetStockObject(BLACK_PEN));DrawHands(hdc, &st, TRUE);ReleaseDC(hwnd, hdc);stPrevious = st;return 0;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);SetIsotropic(hdc, cxClient, cyClient);DrawClock(hdc);DrawHands(hdc, &stPrevious, TRUE);EndPaint(hwnd, &ps);return 0;case WM_DESTROY:KillTimer(hwnd, ID_TIMER);PostQuitMessage (0) ;return 0 ;}return DefWindowProc (hwnd, message, wParam, lParam) ;}
4.在状态报告中使用计时器
/*----------------------------------------------------------- whatclr.cpp -- Displays Color Under Cursor------------------------------------------------------------*/#include <windows.h>#define ID_TIMER1void FindWindowSize(int* , int* );LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){static TCHAR szAppName[] = TEXT("WhatClr");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if (!RegisterClass (&wndclass)){MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);return 0 ;}hwnd = CreateWindow(szAppName, TEXT ("What Color"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);ShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}void FindWindowSize(int* pcxWindow, int* pcyWindow){HDChdcScreen;TEXTMETRICtm;hdcScreen = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);GetTextMetrics(hdcScreen, &tm);DeleteDC(hdcScreen);*pcxWindow = 2 * GetSystemMetrics(SM_CXBORDER) + 12 * tm.tmAveCharWidth;*pcyWindow = 2 * GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYCAPTION) + 2 * tm.tmHeight;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){static COLORREFcr, crLast;static HDChdcScreen;HDChdc;PAINTSTRUCTps;POINTpt;RECTrc;TCHARszBuffer[16];switch (message){case WM_CREATE:hdcScreen = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);SetTimer(hwnd, ID_TIMER, 100, NULL);return 0;case WM_TIMER:GetCursorPos(&pt);cr = GetPixel(hdcScreen, pt.x, pt.y);SetPixel(hdcScreen, pt.x, pt.y, 0);if (cr != crLast){crLast = cr;InvalidateRect(hwnd, NULL, FALSE);}return 0;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);GetClientRect(hwnd, &rc);wsprintf(szBuffer, TEXT(" %02X %02X %02X "), GetRValue(cr), GetGValue(cr), GetBValue(cr));DrawText(hdc, szBuffer, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);EndPaint(hwnd, &ps);return 0;case WM_DESTROY:DeleteDC(hdcScreen);KillTimer(hwnd, ID_TIMER);PostQuitMessage (0);return 0;}return DefWindowProc (hwnd, message, wParam, lParam);}
- Win32 计时器消息 - WM_TIMER,SetTimer
- Win32 计时器消息 - WM_TIMER,SetTimer
- Win32之SetTimer计时器
- 测试WM_TIMER 消息 以及计时器
- SetTimer定时器与WM_TIMER窗口消息详解
- SetTimer定时器与WM_TIMER窗口消息详解
- VC中定时器的使用(SETTIMER,KILLTIMER,WM_TIMER消息)
- WM_TIMER--SetTimer的函数
- WM_TIMER--SetTimer的函数
- SetTimer 计时器是不精确的(WIN32 计时器)
- 计时器SetTimer
- 孙鑫VC++深入详解:Lesson5 Part4 屏幕字符串滚动输出,DrawText,SetTimer,WM_Timer消息
- MFC中的setTimer和WM_TIMER实现
- WM_TIMER消息莫名失踪
- WM_TIMER消息的使用方法
- Windows WM_TIMER消息
- WM_TIMER 消息的问题
- WM_TIMER消息映射(转)
- CKEDITOR 中<p>标签引发的问题
- C++著名程序库的比较和学习经验
- Objective-c 的 @property 详解
- AsyncTask的使用
- 打包python程序为exe文件using cx_freeze
- Win32 计时器消息 - WM_TIMER,SetTimer
- 看看吧
- 猜猜看
- 练练
- ActionScript基础之学习笔记
- PHP提交表单后如何控制缓存
- 宏定义中的空格
- Oracle数据导入导出imp/exp
- objective-c 关于 self 的用法总结