Win32:Windows 窗口的原理,既可以编 32 位也可以编 64 位
WM:Windows Message
文章图片
创建窗口的窗口类型名要写第一步、第二步注册窗口的类型名,否则会导致创建窗口失败
下面来解析 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 函数很多次,会打印调试信息很多次
调试导致以下问题,直接去掉即可,就不会输出下面的信息:
文章图片
窗口句柄:都是相同的,是同一个窗口
文章图片
文章图片
文章图片
当窗口大小发生改变的时候,会发出这个消息,应用程序将使用这个消息,去改变默认的大小值和位置
WM_GETMINMAXINFO 消息 (Winuser.h) - Win32 apps | Microsoft Docs
文章图片
NC:非客户区
C:客户区
非客户区的创建
文章图片
非客户区自动计算大小
文章图片
窗口创建消息:客户区的创建
文章图片
消息分为入队列消息和不入队列消息
进队列的消息
不进队列的消息:不需要 GetMessage 去取消息,例如 WM_CREATE
GetMessage:从消息队列去取消息
WPARAM wParam,LPARAM lParam 为附加信息
文章图片
会把创建窗口信息的值传到 lParam 中
正向缩进 tab,反向缩进 shift + tab
文章图片
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 --- 常用消息以及消息附加参数】
文章图片
或者直接输入
文章图片
按 F10 单步调试后
IPCreateParams 创建窗口时需要传递的信息 NULL:没有要传递的,如果传入某个值,那个值就被传到 IPCreateParams,注意传的是指针
文章图片
检查窗口类型名,注意每一个应用程序都有一个窗口类型名
为什么要有窗口类型名?
任何一个窗口都有一个窗口类型名→ 检查窗口类型名
spy++:一个是 32位,一个是 64位
文章图片
文章图片
点击查找窗口,按住鼠标移动到想要检查的窗口即可
文章图片
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
文章图片
文章图片
很多需要初始化的东西都可以放在 WM_CREATE 中
else
{
break;
}
//如果不想自己处理、处理不了. . . 调用这个函数就交给操作系统处理
无论是否点了退出,最终都会执行这条语句:return DefWindowProc(hWnd,uMsg,wParam,lParam);
点击是
文章图片
文章图片
文章图片
点击否,窗口也被关闭
文章图片
文章图片
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下的C++网络请求
- 计算机使用|什么是压缩文件/压缩包()
- Windows|分享Silverlight/WPF/Windows Phone/HTML5一周学习导读(3月26日-3月31日)
- WINDOWS.H already included.MFC apps must not #i
- windows 下使用SCP命令传递文件/文件夹到Liunx系统
- C#|详解 .Net6 Minimal API 的使用方式
- windows核心编程|QQ群的一次聊天记录
- Appium环境搭建(Windows版)
- Appium基础二(Appium的安装(基Windows))