Win32 SDK基础(十)之详解几种常见的Windows消息处理的示例代码
发布时间 - 2017-06-06 00:00:00 点击率:次一 引言
本文主要介绍几种Windows常见的消息的处理,在《Win32 SDK基础(8)—— Windows消息机制》中,我们介绍了WM_CREATE消息的处理,在窗口创建之前,我们利用消息处理函数弹出了一个MessageBox,本文在此基础之上,介绍WM_DESTROY、WM_SYSCOMMAND、WM_QUIT、WM_SIZE等其它常见的Windows消息。首先,我们引入在《Win32 SDK基础(8)—— Windows消息机制》文中的代码,后续的实验都在此代码的基础之上。
#include "stdafx.h"
#include "MessageTs.h"
HINSTANCE g_hInstance = 0;
//窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage返回0
break;
case WM_CREATE:
MessageBox(NULL,"WM_CREATE消息被处理了","消息处理",MB_OK);
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//注册窗口类
BOOL Register(LPSTR lpClassName, WNDPROC wndProc)
{
WNDCLASSEX wce = { 0 };
wce.cbSize = sizeof(wce);
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wce.hCursor = NULL;
wce.hIcon = NULL;
wce.hIconSm = NULL;
wce.hInstance = g_hInstance;
wce.lpfnWndProc = wndProc;
wce.lpszClassName = lpClassName;
wce.lpszMenuName = NULL;
wce.style = CS_HREDRAW | CS_VREDRAW;
ATOM nAtom = RegisterClassEx(&wce);
if (nAtom == 0)
return FALSE;
return true;
}
//创建主窗口
HWND CreateMain(LPSTR lpClassName, LPSTR lpWndName)
{
HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hInstance, NULL);
return hWnd;
}
//显示窗口
void Display(HWND hWnd)
{
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
}
//消息循环
void Message()
{
MSG nMsg = { 0 };
while (GetMessage(&nMsg, NULL, 0, 0))
{
TranslateMessage(&nMsg);
DispatchMessage(&nMsg);
}
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// TODO: Place code here.
g_hInstance = hInstance;
BOOL nRet = Register("Main", WndProc);
if (!nRet)
{
MessageBox(NULL, "注册失败", "Infor", MB_OK);
return 0;
}
HWND hWnd = CreateMain("Main", "window");
Display(hWnd);
Message();
return 0;
}二、WM_CREATE消息
我们还是要再介绍下wm_create消息。因为在上一文中我们只通过弹出messagebox验证了wm_create消息的产生时机,却没有介绍它另外一个很重要的构成——wparam和lparam参数。我们在发送消息时,往往可以通过这两个参数携带一些信息。wm_create消息是我们在创建窗口时由系统自动发送的消息,同样也会利用这两个参数携带信息。lparam携带了我们创建窗口的createwindowex的12个参数信息,wparam没有被使用,下面我们在处理wm_create消息时,在弹出的对话框上显示窗口类和窗口名称。
//窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage返回0
break;
case WM_CREATE:
{
CREATESTRUCT crt = *((CREATESTRUCT*)lParam);
char buf[256] = {0};
sprintf(buf,"创建的窗口类名称是%s,窗口名称是%s",crt.lpszClass,crt.lpszName);
MessageBox(NULL, buf, "消息处理", MB_OK);
}
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}运行程序,我们发现在窗口创建之前我们成功捕获了窗口的注册窗口类名称和窗口名称,并在对话框上显示出来:
三、WM_DESTROY消息
这个消息在之前的文章中我们其实早已经解除过。他是Windows窗口关闭时发送的一个消息,简单点说就是,当你点击Windows窗口的关闭按钮时,会发出这个消息。我们在之前的代码中,处理这个消息的操作是PostQuitMessage(0),这其实是我们发送了一个接下来要介绍的WM_QUIT消息用来结束程序的进程。WM_DESTORY消息的LPARAM和WPARAM都没被使用,它一般被用来做一些窗口关闭前资源的回收和内存的释放工作等等,我们调用的PostQuitMessage(0)就是一个很常见的用法。
四、WM_QUIT消息
前面我们已经介绍过,这是我们使用PostQuitMessage(0)发送的一个消息,用来结束程序进程,它的WMPARAM是PostQuitMessage中传递的参数,LPARAM参数未被使用。通常情况下我们发送了WM_QUIT后,会引起消息循环中的GetMessage函数返回,从而使
得进程退出。WM_QUIT消息是无法传递到我们自己的窗口处理函数中的。但是我们可以从侧面验证有这么一个消息:我们先在代码中增加对WM_QUIT消息的处理。
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);//可以使GetMessage返回0
break;
case WM_CREATE:
{
CREATESTRUCT crt = *((CREATESTRUCT*)lParam);
char buf[256] = {0};
sprintf(buf,"创建的窗口类名称是%s,窗口名称是%s",crt.lpszClass,crt.lpszName);
MessageBox(NULL, buf, "消息处理", MB_OK);
}
case WM_QUIT:
{
int param = (int)wParam;
char buf[256];
sprintf(buf, "进程退出,退出码:%d", param);
MessageBox(NULL, buf, "消息处理", MB_OK);
}
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}运行程序,在关闭处理WM_CREATE消息的对话框后,发现弹出了我们验证WM_QUIT消息的对话框。
这是因为,弹出的处理WM_CREATE消息MessageBox也是一个窗口,但它属于我们的进程。每个窗口都有一个消息循环,但是消息队列一个进程却只有一个,当MessageBox的窗口关闭时,它的窗口处理函数也调用PostQuitMessage(0)发送了一个WM_QUIT消息。它的消息循环中GetMessage接收到WM_QUIT消息后返回并退出。而这个消息又会被我们的消息循环捕获到,但是由于它不是我们的窗口发出的消息,所以不会导致我们的GetMessage返回结束循环,反而被传给我们的窗口处理函数汇总进行处理,所以出现了上面截图显示的对话框。
五、WM_SYSCOMMAND消息
系统命令消息,当我们点击最大化、最小化和关闭命令时会触发这个消息(这么说来点击关闭按钮时会同时触发WM_DESTROY和WM_SYSCOMMAND两个消息哦)。它的wParam参数携带了具体的窗口操作:
关闭:SC_CLOSE
最大化:SC_MAXIMIZE
最小化:SC_MINIMIZE
这里只列举了三种常见的WM_SYSCOMMAND携带的参数宏,其它的可以参照MSDN。WM_SYSCOMMAND的lParam携带的是产生该消息的鼠标的位置,位置的X和Y坐标分别被存放在lParam的低位和高位字中,我们用下面的代码来验证在窗口最大化时,我们鼠标的位置:
case WM_SYSCOMMAND:
{
if (wParam == SC_MAXIMIZE)
{
short x = LOWORD(lParam);
short y = HIWORD(lParam);
char buf[256];
sprintf(buf, "窗口最大化,x坐标:%d,y坐标:%d", x,y);
MessageBox(NULL, buf, "消息处理", MB_OK);
}
}
当我们点击窗口的最大化按钮时,出现下面的提示:
六 WM_SIZE消息
每当我们调整窗口的大小时,都会触发WM_SIZE消息。它的wParam参数携带的是该消息产生的原因:
SIZE_RESTORED —— 重新调整窗口大小
SIZE_MAXIMIZED —— 最大化显示
SIZE_ MINIMIZED —— 最小化显示
其他参数宏详见MSDN
它的lParam参数携带的是重新调整大小后的窗口的高和宽,其中低字节代表宽,高字节代表高,这里我们通过代码验证,当窗口最大化后窗口的高和宽:
case WM_SIZE:
{
if (wParam == SIZE_MAXIMIZED)
{
short width = LOWORD(lParam);
short hight = HIWORD(lParam);
char buf[256];
sprintf(buf, "窗口最大化,高度:%d,宽度:%d", hight, width);
MessageBox(NULL, buf, "消息处理", MB_OK);
}
}运行程序,最大化时可以显示最大化后的窗口高度和宽度:
# windows
# 的是
# 对话框
# 弹出
# 送了
# 鼠标
# 在此
# 这两个
# 当我们
# 基础之上
# 自己的
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel安装步骤详细教程_Laravel环境搭建指南
php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】
香港服务器网站卡顿?如何解决网络延迟与负载问题?
大同网页,大同瑞慈医院官网?
Laravel如何处理文件下载请求?(Response示例)
iOS UIView常见属性方法小结
如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】
javascript基本数据类型及类型检测常用方法小结
Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】
个人网站制作流程图片大全,个人网站如何注销?
深圳网站制作的公司有哪些,dido官方网站?
java中使用zxing批量生成二维码立牌
非常酷的网站设计制作软件,酷培ai教育官方网站?
IOS倒计时设置UIButton标题title的抖动问题
iOS验证手机号的正则表达式
html如何与html链接_实现多个HTML页面互相链接【互相】
Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑
专业商城网站制作公司有哪些,pi商城官网是哪个?
Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权
jQuery 常见小例汇总
Python文本处理实践_日志清洗解析【指导】
Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives
如何在腾讯云服务器上快速搭建个人网站?
Laravel如何使用Service Provider服务提供者_Laravel依赖注入与容器绑定【深度】
如何快速搭建高效香港服务器网站?
Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】
Laravel怎么生成URL_Laravel路由命名与URL生成函数详解
Laravel如何构建RESTful API_Laravel标准化API接口开发指南
html5的keygen标签为什么废弃_替代方案说明【解答】
Python文件操作最佳实践_稳定性说明【指导】
Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
Laravel如何清理系统缓存命令_Laravel清除路由配置及视图缓存的方法【总结】
如何快速生成橙子建站落地页链接?
高防服务器租用如何选择配置与防御等级?
laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法
如何用搬瓦工VPS快速搭建个人网站?
作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】
Laravel观察者模式如何使用_Laravel Model Observer配置
高性能网站服务器配置指南:安全稳定与高效建站核心方案
如何正确选择百度移动适配建站域名?
laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析
百度输入法ai组件怎么删除 百度输入法ai组件移除工具
如何快速搭建高效可靠的建站解决方案?
如何快速上传自定义模板至建站之星?
谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程
Edge浏览器如何截图和滚动截图_微软Edge网页捕获功能使用教程【技巧】
Laravel项目如何进行性能优化_Laravel应用性能分析与优化技巧大全
千库网官网入口推荐 千库网设计创意平台入口
西安专业网站制作公司有哪些,陕西省建行官方网站?

