Windows 第八章 计时器
BEEPER1.cpp 代码 隔一秒换背景颜色 10秒后关闭窗口
#include <Windows.h>
#define ID_TIMER 1
#define ID_TIMER2 2
LRESULT CALLBACK WndPorc(HWND, UINT, WPARAM, LPARAM);//设置回调函数 WndProc函数的返回值类型为LRESULT。该类型等价于LONG.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprevInstance, PSTR szCmdLine, int iCmdShow)
{
static WCHAR szAppName[] = TEXT("HelloWindows"); //定义app名称
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定窗口类型,各种“类风格”(详见下方↓)可以使用按位或操作符组合起来
wndclass.lpfnWndProc = WndPorc; //指定窗口过程(必须是回调函数) *
//下面两个字段用于在类结构和 Windows内部维护的窗口结构中预留
//一些额外的空间:
wndclass.cbClsExtra = 0; //预留的额外空间,一般为 0
wndclass.cbWndExtra = 0; //预留的额外空间,一般为 0
//接下来的字段表示应用程序的实例句柄(是WinMain的一个参数):
wndclass.hInstance = hInstance; //应用程序的实例句柄
//下面的语句为所有基于该窗口类的窗口设定一个图标:
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //为所有基于该窗口类的窗口设定一个图标
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //为所有基于该窗口类的窗口设定一个鼠标指针
/*
下一个字段为这类窗口的客户区指定了背景色。
字段名hbrBackground 的前缀hbr表示“画刷的句柄”(handle to a brush)。
画刷是一个图形学术语,表示用于区域填充的像素着色模式。
Windows有几个标准的画刷,又称“库存”画刷。
下面对GetStockObject的调用返回一个白色画刷的句柄:
*/
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //指定窗口背景色
//接下来的一个字段指定了窗口类的菜单。
//由于程序 HELLOWIN不带任何菜单,所以该字段被设为NULL:
wndclass.lpszMenuName = NULL; //指定窗口菜单
//最后,必须为窗口类赋予一个名称。对一个小程序来说,
//这个名称可以简单地用程序名表示,
//如保存在变量szAppName中的字符串“HelloWin”:
wndclass.lpszClassName = szAppName; //指定窗口类名 *
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, //窗口类名
TEXT("THIS IS YANXU WINDOWS"), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口样式
CW_USEDEFAULT, //初始x位置
CW_USEDEFAULT, //初始y位置
CW_USEDEFAULT, //初始x尺寸
CW_USEDEFAULT, //初始y尺寸
NULL, //父窗口句柄
NULL, //窗口菜单句柄
hInstance, //程序实例句柄
NULL //创建参数
);
ShowWindow(hwnd, iCmdShow); //显示窗口 函 数用于设置窗口的显示状态。
UpdateWindow(hwnd); //函数绕过应用程序的消息队列,直接发送 WM_PAINT 消息给指定窗口的窗口过程
while (GetMessage(&msg, NULL, 0, 0)) //函数的作用是从当前线程的消息队列里获取一个消息并填入 MSG 结构 中。
{
TranslateMessage(&msg); //函数将虚拟键消息转换为字符消息,字符消息被寄送到当前线程的消息队列里。
DispatchMessage(&msg); //函数分派一个消息给窗口过程(回调函数),通常该消息从 GetMessage 函数获得。Windows 的控制权在该函数交给了应用程序。
}
return msg.wParam;
}
LRESULT CALLBACK WndPorc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
static BOOL fFileFlop = FALSE;
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
HBRUSH hBrush;
switch (message)
{
case WM_CREATE: // 当要获取系统的字体时
//PlaySound(TEXT("Helloein.wav"), NULL, SND_FILENAME | SND_ASYNC);
//hdc = GetDC(hwnd);//获取窗口消息
SetTimer(hwnd, ID_TIMER, 1000, NULL);//设置计时器
SetTimer(hwnd, ID_TIMER2, 10000, NULL);
//ReleaseDC(hwnd,hdc);//销毁
return 0;
case WM_TIMER:
switch (wparam)
{
case ID_TIMER:
MessageBeep(-1);//播放声音
fFileFlop = !fFileFlop;//取反 BOOL类型
InvalidateRect(hwnd, NULL, FALSE);//该函数向指定的窗体更新区域添加一个矩形,然后窗体跟新区域的这一部分将被重新绘制。
break;
case ID_TIMER2:
KillTimer(hwnd, ID_TIMER);结束计时器
KillTimer(hwnd, ID_TIMER2);结束计时器
PostQuitMessage(0);//关闭窗口
break;
default:
break;
}
return 0;
case WM_PAINT: //绘制窗口
hdc = BeginPaint(hwnd, &ps); //Device Context设备上下文
//GetClientRect(hwnd,&rect); //获得客户区的位置坐标
//DrawText(hdc,TEXT("这是阎旭的第一个Windows窗口程序!"),-1,&rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER);
GetClientRect(hwnd, &rect);// 获得控件相对与对话框或者(设备屏幕)的坐标大小。
hBrush = CreateSolidBrush(fFileFlop ? RGB(255, 0, 0) : RGB(0, 0, 255));//画背景 红色 or 蓝色
FillRect(hdc, &rect, hBrush);//画布上绘制已填充的矩形
//TextOut(hdc,400,300,TEXT("Yan Xu King!"),12);
EndPaint(hwnd, &ps);
DeleteObject(hBrush);//删除画刷
return 0;
case WM_DESTROY: //处理窗口关闭的消息
KillTimer(hwnd, ID_TIMER);//结束计时器
KillTimer(hwnd, ID_TIMER2);//结束计时器
PostQuitMessage(0);//关闭窗口
return 0;
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
BEEPER2.cpp 跟上面差不多 隔一秒换一种颜色 把计时器处理换为CALLBACK函数处理
#include <Windows.h>
#define ID_TIMER 1
#define ID_TIMER2 2
LRESULT CALLBACK WndPorc(HWND, UINT, WPARAM, LPARAM);//设置回调函数 WndProc函数的返回值类型为LRESULT。该类型等价于LONG.
void CALLBACK TimerProc(HWND, UINT, UINT, DWORD);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprevInstance, PSTR szCmdLine, int iCmdShow)
{
static WCHAR szAppName[] = TEXT("HelloWindows"); //定义app名称
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定窗口类型,各种“类风格”(详见下方↓)可以使用按位或操作符组合起来
wndclass.lpfnWndProc = WndPorc; //指定窗口过程(必须是回调函数) *
//下面两个字段用于在类结构和 Windows内部维护的窗口结构中预留
//一些额外的空间:
wndclass.cbClsExtra = 0; //预留的额外空间,一般为 0
wndclass.cbWndExtra = 0; //预留的额外空间,一般为 0
//接下来的字段表示应用程序的实例句柄(是WinMain的一个参数):
wndclass.hInstance = hInstance; //应用程序的实例句柄
//下面的语句为所有基于该窗口类的窗口设定一个图标:
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //为所有基于该窗口类的窗口设定一个图标
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //为所有基于该窗口类的窗口设定一个鼠标指针
/*
下一个字段为这类窗口的客户区指定了背景色。
字段名hbrBackground 的前缀hbr表示“画刷的句柄”(handle to a brush)。
画刷是一个图形学术语,表示用于区域填充的像素着色模式。
Windows有几个标准的画刷,又称“库存”画刷。
下面对GetStockObject的调用返回一个白色画刷的句柄:
*/
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //指定窗口背景色
//接下来的一个字段指定了窗口类的菜单。
//由于程序 HELLOWIN不带任何菜单,所以该字段被设为NULL:
wndclass.lpszMenuName = NULL; //指定窗口菜单
//最后,必须为窗口类赋予一个名称。对一个小程序来说,
//这个名称可以简单地用程序名表示,
//如保存在变量szAppName中的字符串“HelloWin”:
wndclass.lpszClassName = szAppName; //指定窗口类名 *
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, //窗口类名
TEXT("THIS IS YANXU WINDOWS"), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口样式
CW_USEDEFAULT, //初始x位置
CW_USEDEFAULT, //初始y位置
CW_USEDEFAULT, //初始x尺寸
CW_USEDEFAULT, //初始y尺寸
NULL, //父窗口句柄
NULL, //窗口菜单句柄
hInstance, //程序实例句柄
NULL //创建参数
);
ShowWindow(hwnd, iCmdShow); //显示窗口 函 数用于设置窗口的显示状态。
UpdateWindow(hwnd); //函数绕过应用程序的消息队列,直接发送 WM_PAINT 消息给指定窗口的窗口过程
while (GetMessage(&msg, NULL, 0, 0)) //函数的作用是从当前线程的消息队列里获取一个消息并填入 MSG 结构 中。
{
TranslateMessage(&msg); //函数将虚拟键消息转换为字符消息,字符消息被寄送到当前线程的消息队列里。
DispatchMessage(&msg); //函数分派一个消息给窗口过程(回调函数),通常该消息从 GetMessage 函数获得。Windows 的控制权在该函数交给了应用程序。
}
return msg.wParam;
}
LRESULT CALLBACK WndPorc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
switch (message)
{
case WM_CREATE: // 当要获取系统的字体时
//PlaySound(TEXT("Helloein.wav"), NULL, SND_FILENAME | SND_ASYNC);
//hdc = GetDC(hwnd);//获取窗口消息
SetTimer(hwnd, ID_TIMER, 1000, TimerProc);//设置计时器
//SetTimer(hwnd, ID_TIMER2, 10000, TimerProc);
//ReleaseDC(hwnd,hdc);//销毁
return 0;
case WM_DESTROY: //处理窗口关闭的消息
KillTimer(hwnd, ID_TIMER);//结束计时器
//KillTimer(hwnd, ID_TIMER2);//结束计时器
PostQuitMessage(0);//关闭窗口
return 0;
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
void CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimeriD, DWORD dwTime)
{
static BOOL fFileFlop = FALSE;
HDC hdc;
RECT rect;
HBRUSH hBrush;
MessageBeep(-1);//播放声音
fFileFlop = !fFileFlop;//取反 BOOL类型
GetClientRect(hwnd, &rect);// 获得控件相对与对话框或者(设备屏幕)的坐标大小。
hdc = GetDC(hwnd);//获取窗口消息
hBrush = CreateSolidBrush(fFileFlop ? RGB(255, 0, 0) : RGB(0, 0, 255));//画背景 红色 or 蓝色
FillRect(hdc, &rect, hBrush);//画布上绘制已填充的矩形
ReleaseDC(hwnd, hdc);//销毁
DeleteObject(hBrush);//删除画刷
//SetTimer(hwnd, iTimeriD, dwTime, NULL);
}
DIGLOCK.cpp 显示时钟
#include <Windows.h>
#define ID_TIMER 1
#define ID_TIMER2 2
LRESULT CALLBACK WndPorc(HWND, UINT, WPARAM, LPARAM);//设置回调函数 WndProc函数的返回值类型为LRESULT。该类型等价于LONG.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprevInstance, PSTR szCmdLine, int iCmdShow)
{
static WCHAR szAppName[] = TEXT("HelloWindows"); //定义app名称
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定窗口类型,各种“类风格”(详见下方↓)可以使用按位或操作符组合起来
wndclass.lpfnWndProc = WndPorc; //指定窗口过程(必须是回调函数) *
//下面两个字段用于在类结构和 Windows内部维护的窗口结构中预留
//一些额外的空间:
wndclass.cbClsExtra = 0; //预留的额外空间,一般为 0
wndclass.cbWndExtra = 0; //预留的额外空间,一般为 0
//接下来的字段表示应用程序的实例句柄(是WinMain的一个参数):
wndclass.hInstance = hInstance; //应用程序的实例句柄
//下面的语句为所有基于该窗口类的窗口设定一个图标:
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //为所有基于该窗口类的窗口设定一个图标
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //为所有基于该窗口类的窗口设定一个鼠标指针
/*
下一个字段为这类窗口的客户区指定了背景色。
字段名hbrBackground 的前缀hbr表示“画刷的句柄”(handle to a brush)。
画刷是一个图形学术语,表示用于区域填充的像素着色模式。
Windows有几个标准的画刷,又称“库存”画刷。
下面对GetStockObject的调用返回一个白色画刷的句柄:
*/
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //指定窗口背景色
//接下来的一个字段指定了窗口类的菜单。
//由于程序 HELLOWIN不带任何菜单,所以该字段被设为NULL:
wndclass.lpszMenuName = NULL; //指定窗口菜单
//最后,必须为窗口类赋予一个名称。对一个小程序来说,
//这个名称可以简单地用程序名表示,
//如保存在变量szAppName中的字符串“HelloWin”:
wndclass.lpszClassName = szAppName; //指定窗口类名 *
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, //窗口类名
TEXT("THIS IS YANXU WINDOWS"), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口样式
CW_USEDEFAULT, //初始x位置
CW_USEDEFAULT, //初始y位置
CW_USEDEFAULT, //初始x尺寸
CW_USEDEFAULT, //初始y尺寸
NULL, //父窗口句柄
NULL, //窗口菜单句柄
hInstance, //程序实例句柄
NULL //创建参数
);
ShowWindow(hwnd, iCmdShow); //显示窗口 函 数用于设置窗口的显示状态。
UpdateWindow(hwnd); //函数绕过应用程序的消息队列,直接发送 WM_PAINT 消息给指定窗口的窗口过程
while (GetMessage(&msg, NULL, 0, 0)) //函数的作用是从当前线程的消息队列里获取一个消息并填入 MSG 结构 中。
{
TranslateMessage(&msg); //函数将虚拟键消息转换为字符消息,字符消息被寄送到当前线程的消息队列里。
DispatchMessage(&msg); //函数分派一个消息给窗口过程(回调函数),通常该消息从 GetMessage 函数获得。Windows 的控制权在该函数交给了应用程序。
}
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, fSuppress);
DisplayColon(hdc);
DisplayTwoDigits(hdc, st.wSecond, fSuppress);
}
LRESULT CALLBACK WndPorc(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)
{
case WM_CREATE:
hBrushRed = CreateSolidBrush(RGB(255, 0, 0));
SetTimer(hwnd, ID_TIMER, 1000, NULL);
// 落空
case 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);
}
显示结果
CLOCK.cpp 代码 显示时钟
#include <Windows.h>
#include <math.h>
#define ID_TIMER 1
#define TWOPI (2*3.14159)
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//设置回调函数 WndProc函数的返回值类型为LRESULT。该类型等价于LONG.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprevInstance, PSTR szCmdLine, int iCmdShow)
{
static WCHAR szAppName[] = TEXT("HelloWindows"); //定义app名称
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定窗口类型,各种“类风格”(详见下方↓)可以使用按位或操作符组合起来
wndclass.lpfnWndProc = WndProc; //指定窗口过程(必须是回调函数) *
//下面两个字段用于在类结构和 Windows内部维护的窗口结构中预留
//一些额外的空间:
wndclass.cbClsExtra = 0; //预留的额外空间,一般为 0
wndclass.cbWndExtra = 0; //预留的额外空间,一般为 0
//接下来的字段表示应用程序的实例句柄(是WinMain的一个参数):
wndclass.hInstance = hInstance; //应用程序的实例句柄
//下面的语句为所有基于该窗口类的窗口设定一个图标:
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //为所有基于该窗口类的窗口设定一个图标
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //为所有基于该窗口类的窗口设定一个鼠标指针
/*
下一个字段为这类窗口的客户区指定了背景色。
字段名hbrBackground 的前缀hbr表示“画刷的句柄”(handle to a brush)。
画刷是一个图形学术语,表示用于区域填充的像素着色模式。
Windows有几个标准的画刷,又称“库存”画刷。
下面对GetStockObject的调用返回一个白色画刷的句柄:
*/
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //指定窗口背景色
//接下来的一个字段指定了窗口类的菜单。
//由于程序 HELLOWIN不带任何菜单,所以该字段被设为NULL:
wndclass.lpszMenuName = NULL; //指定窗口菜单
//最后,必须为窗口类赋予一个名称。对一个小程序来说,
//这个名称可以简单地用程序名表示,
//如保存在变量szAppName中的字符串“HelloWin”:
wndclass.lpszClassName = szAppName; //指定窗口类名 *
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, //窗口类名
TEXT("THIS IS YANXU WINDOWS"), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口样式
CW_USEDEFAULT, //初始x位置
CW_USEDEFAULT, //初始y位置
CW_USEDEFAULT, //初始x尺寸
CW_USEDEFAULT, //初始y尺寸
NULL, //父窗口句柄
NULL, //窗口菜单句柄
hInstance, //程序实例句柄
NULL //创建参数
);
ShowWindow(hwnd, iCmdShow); //显示窗口 函 数用于设置窗口的显示状态。
UpdateWindow(hwnd); //函数绕过应用程序的消息队列,直接发送 WM_PAINT 消息给指定窗口的窗口过程
while (GetMessage(&msg, NULL, 0, 0)) //函数的作用是从当前线程的消息队列里获取一个消息并填入 MSG 结构 中。
{
TranslateMessage(&msg); //函数将虚拟键消息转换为字符消息,字符消息被寄送到当前线程的消息队列里。
DispatchMessage(&msg); //函数分派一个消息给窗口过程(回调函数),通常该消息从 GetMessage 函数获得。Windows 的控制权在该函数交给了应用程序。
}
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);
}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static SYSTEMTIME stPrevious;
static int cxClient, cyClient;
BOOL fChange;
HDC hdc;
PAINTSTRUCT ps;
SYSTEMTIME st;
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);
}
结果显示
在状态报告上使用计时器 显示有问题(未解决)
#include <Windows.h>
#define ID_TIMER 1
void FindWindowSize(int*, int*);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//设置回调函数 WndProc函数的返回值类型为LRESULT。该类型等价于LONG.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprevInstance, PSTR szCmdLine, int iCmdShow)
{
static WCHAR szAppName[] = TEXT("HelloWindows"); //定义app名称
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定窗口类型,各种“类风格”(详见下方↓)可以使用按位或操作符组合起来
wndclass.lpfnWndProc = WndProc; //指定窗口过程(必须是回调函数) *
//下面两个字段用于在类结构和 Windows内部维护的窗口结构中预留
//一些额外的空间:
wndclass.cbClsExtra = 0; //预留的额外空间,一般为 0
wndclass.cbWndExtra = 0; //预留的额外空间,一般为 0
//接下来的字段表示应用程序的实例句柄(是WinMain的一个参数):
wndclass.hInstance = hInstance; //应用程序的实例句柄
//下面的语句为所有基于该窗口类的窗口设定一个图标:
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //为所有基于该窗口类的窗口设定一个图标
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //为所有基于该窗口类的窗口设定一个鼠标指针
/*
下一个字段为这类窗口的客户区指定了背景色。
字段名hbrBackground 的前缀hbr表示“画刷的句柄”(handle to a brush)。
画刷是一个图形学术语,表示用于区域填充的像素着色模式。
Windows有几个标准的画刷,又称“库存”画刷。
下面对GetStockObject的调用返回一个白色画刷的句柄:
*/
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //指定窗口背景色
//接下来的一个字段指定了窗口类的菜单。
//由于程序 HELLOWIN不带任何菜单,所以该字段被设为NULL:
wndclass.lpszMenuName = NULL; //指定窗口菜单
//最后,必须为窗口类赋予一个名称。对一个小程序来说,
//这个名称可以简单地用程序名表示,
//如保存在变量szAppName中的字符串“HelloWin”:
wndclass.lpszClassName = szAppName; //指定窗口类名 *
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, //窗口类名
TEXT("THIS IS YANXU WINDOWS"), //窗口标题
WS_OVERLAPPEDWINDOW, //窗口样式
CW_USEDEFAULT, //初始x位置
CW_USEDEFAULT, //初始y位置
CW_USEDEFAULT, //初始x尺寸
CW_USEDEFAULT, //初始y尺寸
NULL, //父窗口句柄
NULL, //窗口菜单句柄
hInstance, //程序实例句柄
NULL //创建参数
);
ShowWindow(hwnd, iCmdShow); //显示窗口 函 数用于设置窗口的显示状态。
UpdateWindow(hwnd); //函数绕过应用程序的消息队列,直接发送 WM_PAINT 消息给指定窗口的窗口过程
while (GetMessage(&msg, NULL, 0, 0)) //函数的作用是从当前线程的消息队列里获取一个消息并填入 MSG 结构 中。
{
TranslateMessage(&msg); //函数将虚拟键消息转换为字符消息,字符消息被寄送到当前线程的消息队列里。
DispatchMessage(&msg); //函数分派一个消息给窗口过程(回调函数),通常该消息从 GetMessage 函数获得。Windows 的控制权在该函数交给了应用程序。
}
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;
}
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)
{
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);
}