1.前缀
前缀 | 全称 | 释义 |
CS | Class Style | 类风格选项 |
CW | Create Windows | 创建窗口选项 |
DT | Draw Text | 绘制文本选项 |
IDI | Icon ID | 图标ID号 |
IDC | Cursor ID | 光标ID号 |
MB | Message Box | 消息框选项 |
SND | Sound | 声音选项 |
WM | Windows Message | 窗口消息 |
WS | Windows Style | 窗口风格 |
2.wParam 和 lParam意义
在Windows是一种16位系统时,WndProc的第三个参数被定义为WORD,是一个16位的无符号整数,而第四个参数被定义为一个LONG,是一个32位有符号整数,所以导致对单词PARAM(参数)加前缀W和L。
但在32位Windows中,WPARAM被定义为一个UINT,而LPARAM被定义为一个LONG,因此窗口过程的这两个参数都是32位的值。
3.注册窗口类RegisterClass
窗口类结构WNDCLASS(WNDCLASSEX):
WNDCLASS wc;
① wc.style:类风格,用于在什么时候发出窗口变化消息
② wc.cbClsExtra:在类结构保存的窗口结构中预留一些额外空间
③ wc.cbWndExtra:在Windows内部保存的窗口结构中预留一些额外空间
④ wc.hbrBackground:指定基于这个类创建的窗口背景颜色
⑤ wc.hCursor:读取光标
⑥ wc.hIcon:读取图标
⑦ wc.hInstance:程序的实例句柄
⑧ wc.lpfnWndProc:指定处理基于这个窗口类创建的所有窗口的消息处理函数(WndProc)
⑨ wc.lpszClassName:指定类名
⑩ wc.lpszMenuName:指定窗口类菜单
4.创建窗口CreateClass
窗口类定义了窗口的一般特征,调用CreateWindow可以指定有关窗口的更详细的信息。
hwnd = CreateWindow (szAppName, // 窗口类名,基于该窗口类创建窗口
TEXT ("Hello Win"), // 这个字符串会出现在标题栏中
WS_OVERLAPPEDWINDOW, // 本窗口风格
CW_USEDEFAULT, //窗口左上角的X坐标
CW_USEDEFAULT, //窗口左上角的Y坐标
CW_USEDEFAULT, //窗口的宽度
CW_USEDEFAULT, //窗口的高度
NULL, //窗口对象的父窗口或所有者窗口句柄
NULL, //菜单句柄
hInstance, //当前进程的实例句柄
NULL) ; //传递给窗口WM_CREATE消息的指针
返回一个窗口句柄。
5.显示窗口
窗口创建成功后,系统将在内存中为其分配一块内存,但是此时窗口并未显示在显示器上,所以需要使用两个调用。
① ShowWindow(窗口句柄,iCmdShow);
其中的第二个参数用于确定如何儿子屏幕上显示窗口,是最小化还是常规还是最大化。
② UpdateWindow(窗口句柄)
调用上句将导致客户区被绘制。它通过给窗口过程发送一个WM_PAINT消息来做到这一点。
6.消息循环
调用UpdateWindow之后,窗口就出现在显示器上。
Windows为当前运行的每个Windows程序维护一个“消息队列”。在发生事件的时候,Windows将事件转换为一个“消息”,并将消息放入程序的消息队列中。
程序通过执行一个叫做“消息循环”的代码从消息队列中取出消息。(注意GetMessage(阻塞,若没有消息则不返还控制权)和PeekMessage(非阻塞,若没有消息也会返回)的区别)
7.消息处理函数(回调函数)WndProc
实际的动作发生在消息处理函数中。消息处理函数确定了在窗口的客户区显示什么,以及怎么处理用户输入。
(1)消息处理函数是命名为WndProc的函数。(也可以其他不冲突的名字)
(2)一个Windows程序可以包含多个消息处理函数。
(3)一个消息处理函数总是与调用RegisterClass注册的特定窗口类相关联。
(4)CreateWindow函数根据特定的窗口类创建一个窗口,返回该窗口的句柄。
(5)但是基于一个窗口类可以创建多个窗口。
1程序 —— 包括 ——n个回调函数
1回调函数 —— 关联 —— 1窗口类
1窗口类 —— 创建 —— n个窗口
窗口过程处理消息时,必须返回0.窗口过程不予处理的所有消息应该被传给名为DefWindowsProc的Windows函数。
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
8.WM_CREATE消息
当Windows在处理CreateWindow函数时,回调函数就会接收到WM_CREATE消息。
9.WM_PAINT消息
当窗口客户区域的一部分或全部变成“无效”时,必须进行刷新,WM_PAINT将通知程序。
在最初创建窗口的时候,整个客户区都是无效的,因为程序还没有在窗口上画任何东西。在调用UpdateWindow时,通常会触发第一个WM_PAINT消息,指示窗口过程在客户区域上画一些东西。
在改变程序窗口大小后,客户区也会变得无效,至于怎么变得无效由CS_引导的类风格选项确定。
----------------------------------------------------------------------------------------------------------------
对WM_PAINT的处理几乎总是从一个BeginPaint调用开始,以一个EndPaint结束。
hdc = BeginPaint(hwnd, &pt);
//do something;(如GetClientRect(hwnd, &rect);)
EndPaint(hwnd, &pt);
hwnd是要刷新的窗口的窗口句柄。pt是指向类型为PAINTSTRUCT的结构指针。
在BeginPaint调用中,如果客户区域的背景还未被擦除,就由Windows来擦除。然后使用注册窗口类的WNDCLASS结构中的hbrBackground域中第一的刷子来删除背景。
BeginPaint调用使整个客户区有效,并返回一个“设备环境句柄”。设备环境是指物理输出设备及其驱动程序。可以利用该“设备环境句柄”在客户区域显示文本和图形。
EndPaint调用释放设备环境句柄。
--------------------------------------------------------------------------------------------------------------
GetClientRect(hwnd, &rect);
第一个参数:程序的窗口句柄;
第二个参数:指向RECT类型的rectangle结构。该结构有4个LONG域,标识客户区域的尺寸。
当改变窗口大小时,WndProc通过调用GetClientRect来获取变化后的窗口大小,重新绘制客户区。
10.WM_DESTROY消息
当用户点击关闭按钮时发生。程序可以通过调用PostQuitMessage以标准方式响应WM_DESTROY消息;
PostQuitMessage(0); // 该函数在程序的消息队列插入一个WM_QUIT消息。
>>关闭程序时的消息响应:
① 用户点击关闭按钮
② 产生WM_SYSCOMMAND消息
③ 产生WM_CLOSE消息响应WM_SYSCOMMAND
④ 产生WM_DESTROY消息响应WM_CLOSE
⑤ 产生WM_QUIT消息响应WM_DESTROY
11.队列消息和非队列消息
队列消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新返回并分配给回调函数。
非队列消息在Windows调用窗口时直接发送给回调函数。
(队列消息基本上是用户输入的结果,还包括时钟消息、刷新消息、退出消息。
非队列消息基本上是来自调用特定的Windows函数。)