第八章 计时器
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);
}
运行结果 1秒响应一次Timer 切换窗口客户区的背景颜色为红或蓝
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;
SYSTEMTIME GetLocalTime 和GetSystemTime
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进制值