消息的产生与处理流程
- MSG 消息结构体
cpp
typedef struct tagMSG {
HWND hwnd; //接收消息的窗口句柄
UINT message; //消息标识符,如WM_CREATE
WPARAM wParam; //消息第一个附加参数
LPARAM lParam; //消息第二个附加参数
DWORD time; //消息投递时间
POINT pt; //产生消息时鼠标光标坐标
} MSG;
● 整个结构体在GetMessage获取消息、DispatchMessage分发消息之间传递,完整保存消息全部信息
- 窗口过程 WndProc 参数对应关系
DispatchMessage(&msg)会把 MSG 结构体拆解,传给窗口过程函数
窗口过程参数 对应 MSG 结构体成员
| 窗口过程参数 | 对应 MSG 结构体成员 |
|---|---|
| HWND hwnd | MSG.hwnd |
| UINT uMsg | MSG.message |
| WPARAM wParam | MSG.wParam |
| LPARAM lParam | MSG.lParam |
调试技巧:用sprintf格式化uMsg消息编号,OutputDebugString输出到 VS 调试输出窗口,即使不操作窗口,系统也会自动产生大量系统消息:WM_CREATE、WM_SIZE、WM_MOVE等
- 基础系统消息列表
| 消息宏 | 十六进制值 | 触发时机 |
|---|---|---|
| WM_NULL | 0x0000 | 空消息 |
| WM_CREATE | 0x0001 | 窗口刚创建完成 |
| WM_DESTROY | 0x0002 | 窗口被销毁 |
| WM_MOVE | 0x0003 | 窗口发生移动 |
| WM_SIZE | 0x0005 | 窗口大小改变 |
| WM_ACTIVATE | 0x0006 | 窗口激活 / 失去激活 |
● 这类属于内核生成的系统消息,不需要用户操作就会自动产生
● 处理原则:自己关心的消息手动处理;其余全部交给DefWindowProc做系统默认处理
cpp
LRESULT CALLBACK WndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
//窗口初始化资源
return 0;
case WM_DESTROY:
PostQuitMessage(0); //发送WM_QUIT,结束消息循环
return 0;
default:
//未处理消息交给系统默认处理
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
}
⚠ WM_DESTROY 重点考点
● 用户点击窗口关闭按钮,会触发WM_DESTROY
● 必须调用PostQuitMessage(0),往消息队列放入WM_QUIT
● 如果漏掉这行:窗口看不见销毁了,进程仍然驻留在内存,任务管理器还能看到进程
- 消息命名规则
● 前缀WM_ = Windows Message,代表窗口消息
● 消息 ID 按功能分类编号
键盘相关消息
| 消息宏 | 十六进制值 | 说明 |
|---|---|---|
| WM_KEYDOWN | 0x0100 | 按键按下原始消息 |
| WM_KEYUP | 0x0101 | 按键松开原始消息 |
| WM_CHAR | 0x0102 | 字符消息,需要 TranslateMessage 转换才会产生 |
- WM_KEYDOWN
○ wParam:虚拟键码
○ lParam:32 位复合状态
■ 0‑15 位:按键重复计数
■ 第 30 位:按键之前的状态,1 代表之前已经按下 - WM_CHAR
○ wParam直接存放字符 ASCII 码,可以用%c打印字符
○ 只有调用TranslateMessage(&msg),才会把WM_KEYDOWN转换成WM_CHAR
○ 如果消息循环删掉TranslateMessage,程序永远收不到WM_CHAR
重要提醒:不同消息下 wParam、lParam 含义完全不一样,不能凭记忆猜,要查阅 MSDN 文档
例:WM_DESTROY中 wParam、lParam 无意义;WM_KEYDOWN中 wParam 是虚拟键码
完整消息流转链路
GetMessage取出消息 → TranslateMessage(键盘消息转换,生成WM_CHAR)→ DispatchMessage(拆解参数调用WndProc窗口过程)
总结
- DispatchMessage把 MSG 结构体拆成 4 个参数交给窗口过程
- 不写PostQuitMessage(0),窗口关闭但进程不会退出
- TranslateMessage的唯一作用:将原始按键消息转为字符消息WM_CHAR
- 所有 case 处理完毕,default 分支必须返回 DefWindowProc,否则窗口会出现异常行为
- 参数wParam、lParam含义随消息类型变化,没有通用含义,以 MSDN 为准