Windows|Windows --- 常用消息以及消息附加参数

Win32:Windows 窗口的原理,既可以编 32 位也可以编 64 位
WM:Windows Message
Windows|Windows --- 常用消息以及消息附加参数
文章图片

创建窗口的窗口类型名要写第一步、第二步注册窗口的类型名,否则会导致创建窗口失败
下面来解析 Windows 中常用的消息:
窗口处理函数会处理很多消息,会处理哪些消息呢?下面来监测一下这些消息是什么
Windows|Windows --- 常用消息以及消息附加参数
文章图片

//窗口处理函数 LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { //定义一个字符串 wchar_t szMsg[100]; //多字节用 sprintf //格式化-> 宽字符用 wsprintf //把格式化的字符串存储到szMsg中,格式化窗口句柄hWnd 用十六进制显示 #会自动加前缀 wsprintf(szMsg,L"hWnd:%#x\tuMsg:%#x\twParm:%#x\tlParam:%#x\n",hWnd,uMsg,wParam,lParam); //用于输出调试信息 OutputDebugString(szMsg); switch(uMsg) { //窗口客户区创建消息,出来的比较早的一个消息,此时主窗口已经创建好了,只不过没有显示出来 case WM_CREATE: //父窗口为hWnd:当前创建的窗口 //CreateWindow 函数的调用或者CreateWindowEx 函数的调用会发出 WM_CREATE 消息 MessageBox(hWnd,"这是WM_CREATE消息",L"提示",MB_OK); //设置窗口的标题 要设置的窗口 要设置的标题 SetWindowText(hWnd,L"windows编程"); break; } }WINBASEAPI VOID WINAPI OutputDebugStringW( _In_opt_ LPCWSTR lpOutputString ); #ifdef UNICODE #define OutputDebugStringOutputDebugStringW

窗口出来之前会有消息, 会调用WindowProc 函数很多次,会打印调试信息很多次
调试导致以下问题,直接去掉即可,就不会输出下面的信息:
Windows|Windows --- 常用消息以及消息附加参数
文章图片

窗口句柄:都是相同的,是同一个窗口
Windows|Windows --- 常用消息以及消息附加参数
文章图片

Windows|Windows --- 常用消息以及消息附加参数
文章图片

Windows|Windows --- 常用消息以及消息附加参数
文章图片

当窗口大小发生改变的时候,会发出这个消息,应用程序将使用这个消息,去改变默认的大小值和位置
WM_GETMINMAXINFO 消息 (Winuser.h) - Win32 apps | Microsoft Docs
Windows|Windows --- 常用消息以及消息附加参数
文章图片

NC:非客户区
C:客户区
非客户区的创建
Windows|Windows --- 常用消息以及消息附加参数
文章图片

非客户区自动计算大小
Windows|Windows --- 常用消息以及消息附加参数
文章图片

窗口创建消息:客户区的创建
Windows|Windows --- 常用消息以及消息附加参数
文章图片

消息分为入队列消息和不入队列消息
进队列的消息
不进队列的消息:不需要 GetMessage 去取消息,例如 WM_CREATE
GetMessage:从消息队列去取消息
WPARAM wParam,LPARAM lParam 为附加信息
Windows|Windows --- 常用消息以及消息附加参数
文章图片

会把创建窗口信息的值传到 lParam 中
正向缩进 tab,反向缩进 shift + tab
Windows|Windows --- 常用消息以及消息附加参数
文章图片

LPARAM 指向结构体 CREATESTRUCT 的指针
typedef struct tagCREATESTRUCTW { LPVOIDlpCreateParams; HINSTANCEhInstance; //应用程序实例句柄 HMENUhMenu; //菜单句柄 HWNDhwndParent; //父窗口句柄 intcy; //窗口的高度 intcx; //窗口的宽度 inty; //窗口左上角纵坐标 intx; //窗口左上角横坐标 LONGstyle; //风格 LPCWSTRlpszName; //窗口名 LPCWSTRlpszClass; //窗口类型名 DWORDdwExStyle; //窗口的拓展风格 } CREATESTRUCTW, *LPCREATESTRUCTW; #ifdef UNICODE typedef CREATESTRUCTW CREATESTRUCT;

//窗口处理函数 LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { wchar_t szMsg[100]; wsprintf(szMsg,L"hWnd:%#x\tuMsg:%#x\twParm:%#x\tlParam:%#x\n",hWnd,uMsg,wParam,lParam); OutputDebugString(szMsg); switch(uMsg) { case WM_CREATE: //指向结构体的指针-> 强制类型转换为 LPCREATESTRUCT 任何指针都是指向四个字节 LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam; } }

在 case 中定义变量一定要加 { },表示是一个语句块, 不加 { } 会出现问题
Windows|Windows --- 常用消息以及消息附加参数
文章图片

开始调试的同时,打开监视窗口
Windows|Windows --- 常用消息以及消息附加参数
文章图片

选中变量,拖动到监视窗口中
Windows|Windows --- 常用消息以及消息附加参数
文章图片

【Windows|Windows --- 常用消息以及消息附加参数】 Windows|Windows --- 常用消息以及消息附加参数
文章图片

或者直接输入
Windows|Windows --- 常用消息以及消息附加参数
文章图片

按 F10 单步调试后
IPCreateParams 创建窗口时需要传递的信息 NULL:没有要传递的,如果传入某个值,那个值就被传到 IPCreateParams,注意传的是指针
Windows|Windows --- 常用消息以及消息附加参数
文章图片

检查窗口类型名,注意每一个应用程序都有一个窗口类型名
为什么要有窗口类型名?
任何一个窗口都有一个窗口类型名→ 检查窗口类型名
spy++:一个是 32位,一个是 64位
Windows|Windows --- 常用消息以及消息附加参数
文章图片

Windows|Windows --- 常用消息以及消息附加参数
文章图片

点击查找窗口,按住鼠标移动到想要检查的窗口即可
Windows|Windows --- 常用消息以及消息附加参数
文章图片

CreateWindow 中最后一个参数 lParam,int 类型强制转换为指针类型
HWND hWnd = CreateWindow( szAppClassName,//注册窗口的类型名 szWindowName,//窗口的标题 WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINMIZEBOX,//窗口的风格 标题栏|系统菜单 200,//窗口距离屏幕左上角横坐标 200,//窗口距离屏幕左上角纵坐标 800,//窗口的宽度 600,//窗口的高度 NULL,//父窗口句柄 NULL,//菜单句柄 hInstance,//应用程序实例句柄 (LPVOID)10//创建窗口时需要传递的信息 NULL:没有要传递的 ); typedef void far*LPVOID; #define far

Windows|Windows --- 常用消息以及消息附加参数
文章图片

Windows|Windows --- 常用消息以及消息附加参数
文章图片

很多需要初始化的东西都可以放在 WM_CREATE 中
else
{
break;
}
//如果不想自己处理、处理不了. . . 调用这个函数就交给操作系统处理
无论是否点了退出,最终都会执行这条语句:return DefWindowProc(hWnd,uMsg,wParam,lParam);
点击是
Windows|Windows --- 常用消息以及消息附加参数
文章图片

Windows|Windows --- 常用消息以及消息附加参数
文章图片

Windows|Windows --- 常用消息以及消息附加参数
文章图片

点击否,窗口也被关闭
Windows|Windows --- 常用消息以及消息附加参数
文章图片

Windows|Windows --- 常用消息以及消息附加参数
文章图片

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { //窗口关闭消息 case WM_CLOSE: if(IDYES == MessageBox(NULL,L"您确定要退出吗?",L"提示",MB_YESNO)) { //销毁当前处理的窗口句柄-> 发出 WM_DESTROY 信息 DestroyWindow(hWnd); } else {//如果不执行break break; } break; //窗口销毁消息 case WM_DESTROY: //发出一个退出消息 WM_QUIT-> 传入0正常退出 PostQuitMessage(0); break; } //调用操作系统默认窗口处理函数 //如果不想自己处理、处理不了...调用这个函数就交给操作系统处理 return DefWindowProc(hWnd,uMsg,wParam,lParam); }

能不能让它不处理,不想让它调用 DefWindowProc?
WM_CLOSE消息 (Winuser.h) - Win32 apps | Microsoft Docs
在关闭窗口时,不需要传递任何值
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { //窗口关闭消息 case WM_CLOSE: if(IDYES == MessageBox(NULL,L"您确定要退出吗?",L"提示",MB_YESNO)) { //销毁当前处理的窗口句柄-> 发出 WM_DESTROY 信息 DestroyWindow(hWnd); } else { //点击否 最小化 ShowWindow(hWnd,SW_MINIMIZE); //点击否 隐藏运行|托盘 ShowWindow(hWnd,SW_HIDE); return 1; //我已经处理了,不需要你再处理了 //return 0; //我没有处理,你再处理,但是我没有交给操作系统默认处理函数处理 } break; //窗口销毁消息 case WM_DESTROY: //主要做一些清理工作、保存数据-> 凡是程序走到这个地方程序不能还原 不能再显示窗口 ShowWindow(hWnd,SW_MINIMIZE); return 1; //发出一个退出消息 WM_QUIT-> 传入 0 正常退出 PostQuitMessage(0); break; } //调用操作系统默认窗口处理函数 //如果不想自己处理、处理不了...调用这个函数就交给操作系统处理 return DefWindowProc(hWnd,uMsg,wParam,lParam); }

Windows|Windows --- 常用消息以及消息附加参数
文章图片

Windows|Windows --- 常用消息以及消息附加参数
文章图片

    推荐阅读