完整代码注释
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("HelloWin");
HWND hwnd;
MSG msg;
// 窗口类,指定基本的窗口信息,CreateWindow参数指定更详细的信息
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW; // 窗口类样式
wndclass.lpfnWndProc = WndProc; // 窗口消息处理程序
wndclass.cbClsExtra = 0; // 窗口类结构预留空间
wndclass.cbWndExtra = 0; // Windows内部预留空间
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("The Hello Program"), // 窗口标题
WS_OVERLAPPEDWINDOW, // 标准样式的窗口
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); // 重画显示区域,发送消息给消息处理程序
while (GetMessage(&msg, NULL, 0, 0)) // 从消息队列获取消息
{
TranslateMessage(&msg); // 将msg结构传给Windows,进行一些键盘转换
DispatchMessage(&msg); // 调用消息处理程序
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam) // 窗口消息处理程序的四个参数与MSG结构的前四个字段是相同的
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message) {
case WM_CREATE: // 窗口创建时,处理WM_CREATE消息
// 播放声音文件
PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
return 0; // 必须返回0
case WM_PAINT: // 更新画面时,处理WM_PAINT消息
hdc = BeginPaint(hwnd, &ps); // 获得设备内容句柄
GetClientRect(hwnd, &rect); // 设置RECT坐标(窗口大小)
DrawText(hdc, TEXT("你好窗口!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps); // 释放设备内容句柄
return 0;
case WM_DESTROY: // 处理WM_DESTROY消息
// 在程序的消息队列中插入一个WM_QUIT消息,GetMessage会返回0,退出消息循环
PostQuitMessage(0);
return 0;
}
// 不予处理的所有消息应该被传给名为DefWindowProc
return
播放WAV
VS2015引入WINMM.LIB,用来播放WAV:工程,右键属性,链接器,输入,附加依赖项
调用的Windows函数
LoadIcon 加载图标供程序使用。
LoadCursor 加载鼠标光标供程序使用。
GetStockObject 取得一个图形对象(在这个例子中,是取得绘制窗口背景的画刷对象)。
RegisterClass 为程序窗口注册窗口类别。
MessageBox 显示消息框。
CreateWindow 根据窗口类别建立一个窗口。
ShowWindow 在屏幕上显示窗口。
UpdateWindow 指示窗口自我更新。
GetMessage 从消息队列中取得消息。
TranslateMessage 转译某些键盘消息。
DispatchMessage 将消息发送给窗口消息处理程序。
PlaySound 播放一个声音文件。
BeginPaint 开始绘制窗口。
GetClientRect 取得窗口显示区域的大小。
DrawText 显示字符串。
EndPaint 结束绘制窗口。
PostQuitMessage 在消息队列中插入一个「退出程序」消息。
DefWindowProc 执行内定的消息处理。
大写字母标识
前缀 | 类别 | 英文 |
CS | 窗口类别样式 | class style |
CW | 建立窗口 | create window |
DT | 绘制文字 | draw text |
IDI | 图示ID | ID icon |
IDC | 游标ID | ID cursor |
MB | 消息框 | message border |
SND | 声音 | sound |
WM | 窗口消息 | window message |
WS | 窗口样式 | window style |
四种数据结构
结构 | 含义 |
MSG | 消息结构 |
WNDCLASS | 窗口类别结构 |
PAINTSTRUCT | 绘图结构 |
RECT | 矩形结构 |
/*
* 消息数据结构
*/
typedef struct tagMSG {
HWND hwnd; // 接收消息的窗口句柄
UINT message; // 消息标识符
WPARAM wParam; // 32位的消息参数(message parameter)
LPARAM lParam; // 32位的消息参数
DWORD time; // 放入消息队列中的时间
POINT pt; // 消息放入消息队列时的鼠标坐标
#ifdef _MAC
DWORD lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
WM_QUIT消息将导致GetMessage传回0
大写标识符
句柄是一个(通常为32位的)整数,它代表一个对象。
标识符 | 含义 |
HINSTANCE | 执行实体(程序自身)句柄 |
HWND | 窗口句柄 |
HDC | 设备内容句柄 |
HICON | 图标句柄 handle to an icon |
HCURSOR | 鼠标光标句柄 |
HBRUSH | 画刷句柄 |
匈牙利表示法
前缀 | 数据型态 |
c | char或WCHAR或TCHAR |
by | BYTE (无正负号字符) |
n | short |
i | int |
x, y | int分别用作x坐标和y坐标 |
cx, cy | int分别用作x长度和y长度;C代表「计数器」 |
b或f | BOOL (int);f代表「旗标」 |
w | WORD (无正负号短整数) |
l | LONG (长整数) |
dw | DWORD (无正负号长整数) |
fn | function(函数) |
s | string(字符串) |
sz | 以字节值0结尾的字符串 |
h | 句柄 |
p | 指标 |
消息中心
假设使用者执行HELLOWIN,并且使用者最终单击了 Close按钮,或者假设用键盘或鼠标从系统菜单中选择了 Close, DefWindowProc处理这一键盘或者鼠标输入,在检测到使用者选择了Close选项之后,它给窗口消息处理程序发送一条WM_SYSCOMMAND消息。WndProc将这个消息传给DefWindowProc。DefWindowProc给窗口消息处理程序发送一条WM_CLOSE消 息 来 响 应 之 。 WndProc 再 次 将 它 传 给 DefWindowProc 。 DestroyWindow 呼 叫DestroyWindow来响应这条WM_CLOSE消息。DestroyWindow导致Windows给窗口消息处理程序发送一条WM_DESTROY消息。WndProc再呼叫PostQuitMessage,将一条WM_QUIT消息放入消息队列中,以此来响应此消息。这个消息导致WinMain中的消息循环终止,然后程序结束。
消息能够被分为「队列化的」和「非队列化的」。队列化的消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新传回并分配给窗口消息处理程序。非队列化的消息在Windows呼叫窗口时直接送给窗口消息处理程序。也就是说,队列化的消息被「发送」给消息队列,而非队列化的消息则「发送」给窗口消息处理程序。任何情况下,窗口消息处理程序都将获得窗口所有的消息–包括队列化的和非队列化的。
窗口消息处理程序是窗口的”消息中心”。