《Windows程序设计》读书笔八 计时器

第八章  计时器


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 切换窗口客户区的背景颜色为红或蓝

《Windows程序设计》读书笔八 计时器_第1张图片


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进制值



你可能感兴趣的:(windows,Win32)