第八章 计时器
8.1 计时器的基本知识
WM_TIMER消息
SetTimer
Killtimer
8.1.1 系统和计时器
Timer的底层实现是BIOS的时钟中断(时钟滴答),WinNT上由于系统限制1秒最多响应100次。
8.1.2 计时器消息不是异步的
WM_TIMER消息是低优先级的
一个时钟程序只能通过WM_TIMER消息知道时钟更新了,而不应通过该消息来计算过了多少时间。因为他不是精确的时钟滴答中断
8.2 使用计时器的三种方法
如果程序需要计时器,在winmain 函数或者WM_CREATE消息时,调用SetTimer函数。在离开winMain或者处理WM_DESTORY消息时,调用KillTimer函数。
8.2.1 方法一
SetTimer(hwnd, //窗口句柄
1, //计数器ID非0
uiMsecInterval, //以毫秒为单位的时间间隔
NULL) // windows将WM_TIMER消息发送到应用程序的窗口过程
KillTimer(hwnd, 1);
WM_TIMER 消息中 wParam 就是计时器的ID
常用法
#define TIMER_SEC 1
#define TIMER_MIN 2
SetTimer(hwnd, TIMER_SEC, 1000, NULL);
SetTimer(hwnd, TIMEr_MIN, 60000, NULL);
case WM_TIMER:
switch(wParam)
{
case TIMER_SEC:
//do something
break;
case TIMER_MIN:
/do something
break;
}
return 0;
可以改变已有计时器的时间间隔 用SetTimer
一个例子
#include <windows.h> #define ID_TIMER 1 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("Beeper1"); HWND hwnd; MSG msg; WNDCLASS wndClass; //The window Class wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class. 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; //Register the Window Class to the Windows System. if (!RegisterClass(&wndClass)) { MessageBox(NULL, TEXT("This program require Windows NT!"), szAppName, MB_ICONERROR); return 0; } //This function will generate an WM_CREATE message. hwnd = CreateWindow(szAppName, //Window class name TEXT("Beeper1 Timer Demo"), //Window caption WS_OVERLAPPEDWINDOW, //Window Style CW_USEDEFAULT, //initial x position CW_USEDEFAULT, //initial y position CW_USEDEFAULT, //initial x size CW_USEDEFAULT, //initial y size NULL, //parent window handle NULL, //window menu handle hInstance, //program instance handle NULL); //creation parameters ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); //This function will generate a WM_PAINT message. /* The message loop for this program. if received the WM_QUIT message, the function will return 0.*/ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //define the Window Procedure WndProc LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static BOOL fFlipFlop = FALSE; HBRUSH hBrush; HDC hdc; PAINTSTRUCT ps; RECT rc; switch (message) //get the message { case WM_CREATE: SetTimer(hwnd, ID_TIMER, 1000, NULL); return 0; case WM_TIMER: MessageBeep(-1); fFlipFlop = !fFlipFlop; InvalidateRect(hwnd, NULL, FALSE); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rc); hBrush = CreateSolidBrush(fFlipFlop ? RGB(255, 0, 0) : RGB(0, 0, 255)); FillRect(hdc, &rc, hBrush); DeleteObject(hBrush); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: KillTimer(hwnd, ID_TIMER); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
8.2.2 方法二
回调函数
VOID CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
//handle wm_timer message
}
dwTime 记录了windows启动到现在所过去的毫秒数
SetTimer(hwnd, iTimerID, iMsecInterval, TimerProc);
使用TimerProc回调函数来处理WM_TIMER消息的例子
#include <windows.h> #define ID_TIMER 1 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure. VOID CALLBACK 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; //The window Class wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class. 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; //Register the Window Class to the Windows System. if (!RegisterClass(&wndClass)) { MessageBox(NULL, TEXT("This program require Windows NT!"), szAppName, MB_ICONERROR); return 0; } //This function will generate an WM_CREATE message. hwnd = CreateWindow(szAppName, //Window class name TEXT("Beeper2 Timer Demo"), //Window caption WS_OVERLAPPEDWINDOW, //Window Style CW_USEDEFAULT, //initial x position CW_USEDEFAULT, //initial y position CW_USEDEFAULT, //initial x size CW_USEDEFAULT, //initial y size NULL, //parent window handle NULL, //window menu handle hInstance, //program instance handle NULL); //creation parameters ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); //This function will generate a WM_PAINT message. /* The message loop for this program. if received the WM_QUIT message, the function will return 0.*/ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //define the Window Procedure WndProc LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) //get the 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) { static BOOL fFlipFlop = FALSE; HBRUSH hBrush; HDC hdc; RECT rc; MessageBeep(-1); fFlipFlop = !fFlipFlop; GetClientRect(hwnd, &rc); hdc = GetDC(hwnd); hBrush = CreateSolidBrush(fFlipFlop ? RGB(255, 0, 0) : RGB(0, 0, 255)); FillRect(hdc, &rc, hBrush); ReleaseDC(hwnd, hdc); DeleteObject(hBrush); }
8.2.3 方法三
iTimerID = SetTimer(NULL, 0, wMsecInterval, TimerProc);
如果返回0 ,表示没有可调的定时器。
KillTimer(NULL, iTimerID);
8.3 使用计时器作为时钟
8.3.1 数字时钟
#include <windows.h> #define ID_TIMER 1 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("DigClock"); HWND hwnd; MSG msg; WNDCLASS wndClass; //The window Class wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class. 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; //Register the Window Class to the Windows System. if (!RegisterClass(&wndClass)) { MessageBox(NULL, TEXT("This program require Windows NT!"), szAppName, MB_ICONERROR); return 0; } //This function will generate an WM_CREATE message. hwnd = CreateWindow(szAppName, //Window class name TEXT("Digital Clock"), //Window caption WS_OVERLAPPEDWINDOW, //Window Style CW_USEDEFAULT, //initial x position CW_USEDEFAULT, //initial y position CW_USEDEFAULT, //initial x size CW_USEDEFAULT, //initial y size NULL, //parent window handle NULL, //window menu handle hInstance, //program instance handle NULL); //creation parameters ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); //This function will generate a WM_PAINT message. /* The message loop for this program. if received the WM_QUIT message, the function will return 0.*/ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } void DisplayDigit(HDC hdc, int iNumber) { static BOOL fSevenSegment[10][7] = { 1, 1, 1, 0, 1, 1, 1, // 0 0, 0, 1, 0, 0, 1, 0, // 1 1, 0, 1, 1, 1, 0, 1, // 2 1, 0, 1, 1, 0, 1, 1, // 3 0, 1, 1, 1, 0, 1, 0, // 4 1, 1, 0, 1, 0, 1, 1, // 5 1, 1, 0, 1, 1, 1, 1, // 6 1, 0, 1, 0, 0, 1, 0, // 7 1, 1, 1, 1, 1, 1, 1, // 8 1, 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); else DisplayTwoDigits(hdc, (st.wHour %= 12) ? st.wHour : 12, fSuppress); DisplayColon(hdc); DisplayTwoDigits(hdc, st.wMinute, FALSE); DisplayColon(hdc); DisplayTwoDigits(hdc, st.wSecond, FALSE); } //define the Window Procedure WndProc LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static BOOL f24Hour, fSuppress; static HBRUSH hBrushRed; static int cxClient, cyClient; HDC hdc; PAINTSTRUCT ps; TCHAR szBuffer[2]; switch (message) //get the message { case WM_CREATE: hBrushRed = CreateSolidBrush(RGB(255, 0, 0)); SetTimer(hwnd, ID_TIMER, 1000, NULL); //fall through case WM_SETTINGCHANGE: GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 2); f24Hour = (szBuffer[0] == TEXT('1')); GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITLZERO, szBuffer, 2); fSuppress = (szBuffer[0] == TEXT('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); //Set the logical point of the current windows SetViewportExtEx(hdc, cxClient, cyClient, NULL); //Map the logical position to the device position SetWindowOrgEx(hdc, 138, 36, NULL); //Set the logical org position SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL); //Set the device org position 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); }
8.3.2 获取当前时间
typedef struct _SYSTEMTIME { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
SetLocalTime
SetSystemTime
8.3.3 显示数字与冒号
8.3.4 考虑国际化
GetDateFormat
GetTimeFormat 格式化日期和时间
如果时钟每分钟才变化一次 需要处理WM_TIMECHANGE消息
8.3.5 模拟时钟
#include <windows.h> #include <math.h> #define ID_TIMER 1 #define TWOPI (2 * 3.14159) LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("Clock"); HWND hwnd; MSG msg; WNDCLASS wndClass; //The window Class wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class. 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; //Register the Window Class to the Windows System. if (!RegisterClass(&wndClass)) { MessageBox(NULL, TEXT("This program require Windows NT!"), szAppName, MB_ICONERROR); return 0; } //This function will generate an WM_CREATE message. hwnd = CreateWindow(szAppName, //Window class name TEXT("Analog Clock"), //Window caption WS_OVERLAPPEDWINDOW, //Window Style CW_USEDEFAULT, //initial x position CW_USEDEFAULT, //initial y position CW_USEDEFAULT, //initial x size CW_USEDEFAULT, //initial y size NULL, //parent window handle NULL, //window menu handle hInstance, //program instance handle NULL); //creation parameters ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); //This function will generate a WM_PAINT message. /* The message loop for this program. if received the WM_QUIT message, the function will return 0.*/ 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) { int i; POINT ptTemp; 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) { int iAngle; POINT pt[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 }; int i, iAngle[3]; POINT ptTemp[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); } } //define the Window Procedure WndProc LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxClient, cyClient; static SYSTEMTIME stPrevious; BOOL fChange; HDC hdc; PAINTSTRUCT ps; SYSTEMTIME st; switch (message) //get the 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.wMinute); 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); }
8.4 在状态报告上使用计时器
whatclr程序
#include <windows.h> #define ID_TIMER 1 void FindWindowSize(int *, int *); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //window procedure. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("WhatCtr"); HWND hwnd; int cxWindow, cyWindow; MSG msg; WNDCLASS wndClass; //The window Class wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc;// assign the window procedure to windows class. 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; //Register the Window Class to the Windows System. if (!RegisterClass(&wndClass)) { MessageBox(NULL, TEXT("This program require Windows NT!"), szAppName, MB_ICONERROR); return 0; } FindWindowSize(&cxWindow, &cyWindow); //This function will generate an WM_CREATE message. hwnd = CreateWindow(szAppName, //Window class name TEXT("What Color"), //Window caption WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_BORDER, //Window Style CW_USEDEFAULT, //initial x position CW_USEDEFAULT, //initial y position cxWindow, //initial x size cyWindow, //initial y size NULL, //parent window handle NULL, //window menu handle hInstance, //program instance handle NULL); //creation parameters ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); //This function will generate a WM_PAINT message. /* The message loop for this program. if received the WM_QUIT message, the function will return 0.*/ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } void FindWindowSize(int * pcxWindow, int * pcyWindow) { HDC hdcScreen; TEXTMETRIC tm; 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; } //define the Window Procedure WndProc LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static COLORREF cr, crLast; static HDC hdcScreen; HDC hdc; PAINTSTRUCT ps; POINT pt; RECT rc; TCHAR szBuffer[16]; switch (message) //get the 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); }获得屏幕上当前鼠标位置的RGB颜色的16进制值