- 浏览: 16090 次
最新评论
消息分流器(HANDLE_MSG)
2010年10月13日
声明:本文来自百度贴吧(找不到原文地址了)
windows消息分流器的实现,很好理解,windows操作系统使用消息处理机制,那么,我们所设计的程序如何才能分辨和处理系统中的各种消息呢?这就是消息分流器的作用.
简单来说,消息分流器就是一段代码,在我的讲述中,将分7重来循序渐进的介绍它.从最初的第1重到最成熟的第7重,它的样子会有很大的变化.但,实现的功能都是一样的,所不同的,仅仅是变得更加简练罢了.
程序开始时候,会是main函数,然后会生成初始的窗口,同时会调用WndProc函数.这是一个自定义的函数,名字也会有变化,但其功能是一样的,就是运行消息分流器.WndProc函数如下:
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam)
{
//......
return DefWindowProc(hwnd, msg, wParam, lParam);
}
这其中,hwnd是窗口的句柄,msg是系统发送来的消息的名字.wParam和lParam则是随消息一起发送来的消息参数.
WndProc函数使用了消息分流器,下面把消息分流器的内容解释一下:
一重,当不同的消息出现时,在其中写入相应的程序语句即可。
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
// ...
return 0;
case WM_PAINT:
// ...
return 0;
case WM_DESTROY:
//...
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
二重,运用三个消息分流器进行处理。
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
return HANDLE_WM_CREATE(hwnd, wParam, lParam, Cls_OnCreate);
case WM_PAINT:
return HANDLE_WM_PAINT(hwnd, wParam, lParam, Cls_OnPaint);
case WM_DESTROY:
return HANDLE_WM_DESTROY(hwnd, wParam, lParam, Cls_OnDestroy);
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
这里的HANDLE_WM_CREATE,HANDLE_WM_PAINT,HANDLE_WM_DESTROY就是消息分流器。
与消息不同之处就是在前面增加了“HANDLE_”字符,windows的消息分流器就是这样的模样。
它的本质就是宏定义。
其中的四个参数有三个都是从本函数的入口参数中直接得到的,即为hwnd, wParam, lParam。
只有第四的参数是表明调用的函数。
消息分流器是在winowsx.h文件中定义的。由此,可以看出第四个参数是调用的函数,其定义如下:
#define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn) ((fn)((hwnd), (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L)
#define HANDLE_WM_PAINT(hwnd, wParam, lParam, fn) ((fn)(hwnd), 0L)
#define HANDLE_WM_DESTROYCLIPBOARD(hwnd, wParam, lParam, fn) ((fn)(hwnd), 0L)
0L是表示int类型的变量,其数值为0。
int类型时,可在后面加l或者L(小写和大写形式)
表明无符号数时,可在后面加u或者U(小写和大写形式)
float类型时,可在后面加f或者F(小写和大写形式)
例如:
128u 1024UL 1L 8Lu 3.14159F 0.1f
LRESULT是一个系统的数据类型,其定义如下:
typedef LONG_PTR LRESULT;
LONG_PTR也是一个系统的数据类型,其定义如下:
#if defined(_WIN64)
typedef __int64 LONG_PTR;
#else
typedef long LONG_PTR;
#endif
由此可见,LRESULT的实质就是64的long类型的变量
那么(LRESULT)-1L的实质并不是减法,而是((LRESULT)(-1L)),即强制类型转换
三重,把消息分流器的宏定义代换回去,就成了下面的样子
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
return Cls_OnCreate(hwnd, (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L;
// 如果处理了消息,则Cls_OnCreate应返回TRUE,导致WndProc返回0,否则Cls_OnCreate返回FALSE,导致WndProc返回-1;
case WM_PAINT:
return Cls_OnPaint(hwnd), 0L;
// 逗号表达式;Cls_OnPaint是void类型,这里返回0;
case WM_DESTROY:
return Cls_OnDestroy(hwnd), 0L; // 同Cls_OnPaint
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
在逗号表达式,C++会计算每个表达式,但完整的逗号表达式的结果是最右边表达式的值。
所以,会return 0。
然后,就可以手动的编写各个处理函数了:Cls_OnCreate,Cls_OnPaint,WM_DESTROY。
四重,
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate);
HANDLE_MSG(hwnd, WM_PAINT, Cls_OnPaint);
HANDLE_MSG(hwnd, WM_DESTROY, Cls_OnDestroy);
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
HANDLE_MSG也是一个宏,它在windowsx.h中定义,如下:
#define HANDLE_MSG(hwnd, message, fn) case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))
这个宏要做的就是根据不同的message(##用来连接前后的字符串),把自己“变成”相应的HANDLE_XXXXMESSAGE形式的宏,再通过相应的宏来执行消息处理代码。
说白了,就是把message的消息做为替换,##就是一个替换的标志。
如果没有##,就成了HANDLE_message了,这样,宏是不会被代换的。
如果就单独一个,则会代换,如hwnd和fn。
比如实际代码中写入:
HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate)
则经过转换就变成:
case (WM_CREATE): return HANDLE_WM_CREATE((hwnd), (wParam), (lParam), (Cls_OnCreate))
这与二重一模一样。
以上四重,是消息分离器的基本使用,但,这不完整,消息分离器主要应用在对话框消息处理中。
这里,窗口子类化是我们经常使用的手段,这也可以通过消息分流器实现,
第五重
LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG(hwnd, WM_INITDIALO , Cls_OnInitDialog); // 不能直接使用HANDLE_MSG宏
HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand); // 不能直接使用HANDLE_MSG宏
}
return false;
}
由于是窗口子类化,所以,最后,返回的是false,以表明,如果没有约定响应的消息,
则返回父亲窗口false,如果有,则返回ture,这是与前四重不同的地方。
一般情况下,对话框过程函数应该在处理了消息的情况下返回TRUE,如果没有处理,则返回FALSE。
如果对话框过程返回了FALSE,那么对话框管理器为这条消息准备默认的对话操作。
但是,这其中有错误,因为有的消息,需要单独处理。单独处理的消息列表见SetDlgMsgResult宏。
第六重
这点小问题,这就需要用到SetDlgMsgResult(hwnd, msg, result)宏。
LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALO:
return (SetDlgMsgResult(hwnd, Msg, HANDLE_WM_INITDIALO((hwnd), (wParam), (lParam), (fn)));
case WM_COMMAND:
return (SetDlgMsgResult(hwnd, Msg, HANDLE_WM_COMMAND((hwnd), (wParam), (lParam), (fn)));
}
return false;
}
这里,就用直接用到了第二重的消息分流器,而抛弃了其他。
这个宏定义如下:
#define SetDlgMsgResult(hwnd, msg, result)
(
(
(msg) == WM_CTLCOLORMSGBOX ||
(msg) == WM_CTLCOLOREDIT ||
(msg) == WM_CTLCOLORLISTBOX ||
(msg) == WM_CTLCOLORBTN ||
(msg) == WM_CTLCOLORDLG ||
(msg) == WM_CTLCOLORSCROLLBAR ||
(msg) == WM_CTLCOLORSTATIC ||
(msg) == WM_COMPAREITEM ||
(msg) == WM_VKEYTOITEM ||
(msg) == WM_CHARTOITEM ||
(msg) == WM_QUERYDRAGICON ||
(msg) == WM_INITDIALOG
) ?
(BOOL)(result) :
(SetWindowLongPtr((hwnd), DWLP_MSGRESULT, (LPARAM)(LRESULT)(result)), TRUE)
)
为了表述清楚,所以用了此格式,这是一个三项表达式,首先对消息类型进行考察。
如果对话框过程处理的消息恰巧为返回特定值中的一个,则如实返回result;
不要被前面的BOOL蒙蔽,BOOL在头文件中的定义实际上是一个int型,
一旦需要返回非TRUE或FALSE的其他值,照样可以;
这样,我们的Cls_OnInitDialog就能够正确的返回它的BOOL值了,
而Cls_OnCommand在处理之后,也可以由后面的逗号表达式正确的返回一个TRUE表示消息已处理。
第七重
我们还可以把case也包含进来,就成了如下的样子。
LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Cls_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Cls_OnCommand);
}
return false;
}
chHANDLE_DLGMSG是牛人定义的一个宏,它把case也包含进来了。
#define chHANDLE_DLGMSG(hwnd, message, fn) case (message): return (SetDlgMsgResult(hwnd, uMsg, HANDLE_##message((hwnd), (wParam), (lParam), (fn))))
这样,程序中的语句
switch (uMsg)
{
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_SIZE, Dlg_OnSize);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
就被翻译成:
switch (uMsg)
{
case (WM_INITDIALOG):
return (SetDlgMsgResult(hwnd, uMsg, HANDLE_WM_INITDIALOG((hwnd), (wParam), (lParam), (Dlg_OnInitDialog))));
case (WM_SIZE)
return (SetDlgMsgResult(hwnd, uMsg, HANDLE_WM_SIZE((hwnd), (wParam), (lParam), (Dlg_OnSize))));
case (WM_COMMAND)
return (SetDlgMsgResult(hwnd, uMsg, HANDLE_WM_COMMAND((hwnd), (wParam), (lParam), (Dlg_OnCommand))));
}
这样,消息分流器,就介绍完毕.
发表评论
-
高一期中试题
2012-01-20 12:00 794高一期中试题 2012年01月17日 高一年级英语学科( ... -
2012信息技术中考模拟题单选71-140题标准版
2012-01-20 12:00 15292012信息技术中考模拟题单选71-140题标准版 2012 ... -
00000000007
2012-01-20 12:00 77900000000007 2011年10月04日 重要提醒 ... -
巧学宾语从句――宾语从句语法详解 [宾语从句歌诀]
2012-01-20 12:00 1036巧学宾语从句――宾语从句语法详解 [宾语从句歌诀] 2011 ... -
【转】 完型填空复习教案设计
2012-01-20 12:00 755【转】 完型填空复习教案设计 2011年10月01日 完 ... -
VC++日记(非模态,自定义消息,窗体移动……)
2012-01-19 16:49 704VC++日记(非模态,自定义消息,窗体移动……) 2011年 ... -
【转】 消息分流器-HANDLE_MSG
2012-01-19 16:49 709【转】 消息分流器-HANDLE_MSG 2011年05月3 ... -
处理 WM_NCHITTEST 消息实现 WPF 无边框窗体改变大小和移动
2012-01-19 16:49 2809处理 WM_NCHITTEST 消息实现 WPF 无边框窗体改 ... -
VC添加自定义消息(转)
2012-01-19 16:49 882VC添加自定义消息(转) 2011年04月14日 VC的 ... -
灯饰英语
2012-01-17 06:33 613灯饰英语 2011年12月02日 ... -
sysytem32下的文件及其作用的文章
2012-01-17 06:33 508sysytem32下的文件及其作用的文章 2011年11月2 ... -
服务器端发送推送数据
2012-01-17 06:33 710服务器端发送推送数据 ... -
Java语言11个主要特性
2012-01-17 06:33 517Java语言11个主要特性 20 ... -
用PHP代码调用sockets,直接用服务器的网络攻击别的IP
2012-01-17 06:33 553用PHP代码调用sockets,直接用服务器的网络攻击别的IP ... -
今天写写小虎队
2012-01-16 05:14 626今天写写小虎队 2009年1 ... -
夜。上海
2012-01-16 05:14 653夜。上海 2009年08月25日 今天突 ... -
超雷人的 山寨版
2012-01-16 05:14 613超雷人的 山寨版 2009年10月27日 原来不仅仅中 ... -
猜猜我是谁语录
2012-01-16 05:14 657猜猜我是谁语录 2010年0 ...
相关推荐
消息分流器通过宏定义,自动处理这些复杂的参数解析,如HANDEL_MSG宏和HANDLE_WM_COMMAND宏,它们会根据消息类型自动分离和转换wParam和lParam参数,然后调用相应的处理函数,如Cls_OnCommand。 例如,使用消息分流...
标题中的“Transmission_PowerSplitHybrid_Step4_功率分流simulink_amesim_混合动力_”指的是一项基于Simulink和AMESim的混合动力汽车(HEV)功率分流控制策略的第四阶段研究。这项工作重点在于设计和仿真一个能够...
【网络分流器技术详解】 网络分流器,又称为TAP(Terminal Access Point)或NPB(Network Packet Broker),是一种用于网络监控和分析的关键设备。它能够将生产网络中的流量镜像或分发到多个分析设备,而不影响原有...
电流采样电阻-分流器RLP25FEGR010规格书 本规格书详细描述了电流采样电阻-分流器RLP25FEGR010的规格和特性,该产品由TA-I TECHNOLOGY CO., LTD制造,适用于汽车电子应用,满足AEC-Q 200-ver D的资格认证。 一、...
### 元器件分流器的作用及应用 #### 一、引言 在电子技术和电力系统中,经常需要测量较大的电流,而传统的电流表往往无法直接测量这些大电流。为了解决这一问题,通常会使用到一种特殊的元件——分流器。本文将...
《电流采样电阻-分流器 HOT(0.25-1.3)规格书详解》 毫欧电子有限公司生产的C500753电流采样电阻-分流器HOT系列,是一款专为高精度电流测量设计的精密元件。这款电阻系列主要包含三种型号:HoT-(0.45*1.5)-8.2-0R-I...
迈普分流器是一款专业的网络设备,主要用于在网络中实现流量的智能分发和管理。这款设备在企业级网络环境中尤其重要,因为它能够有效地提高网络性能,优化带宽利用,并且有助于故障排查和网络维护。以下是对标题和...
FL-2型外附分流器是一种用于测量大电流的辅助设备,主要应用于电力、工业自动化等领域,用于监测主电路中的电流。它的工作原理是利用欧姆定律,通过自身的低阻抗特性,在大电流通过时产生一个与电流成正比的小电压,...
电流采样电阻-分流器规格书 本规格书详细介绍了电流采样电阻-分流器的规格和技术参数,该设备由深圳市毫欧电子有限公司制造,适用于封体合金电阻HoJLR2512系列产品的选型。 一、产品特点: * 合金芯片,封体工艺...
并联电阻分流电路是电子电路设计中常见的概念,主要用于调整电路中的电流分布,实现电流的分路,以达到特定的设计目标。在本压缩包中,包含了一个名为“并联电阻分流电路仿真.ms11”的Multisim仿真源文件,这为我们...
打开工具,选中要填加的消息事件,在右侧输入窗口类的名称,然后点击核选框make window proc选中(升成窗口过程的意思),之后,左下两个框中会显示要用的信息,分别点击右上的COPY,然后,自己PASTE到程序合适的...
在Windows编程领域,`windowsx.h` 是一个重要的头文件,它包含了许多Windows API的扩展宏,这些宏在...这个"信息分流器"工具进一步降低了使用这些宏的难度,提升了开发效率,是Windows桌面应用程序开发者的得力助手。
电流采样电阻,也称为分流器,是一种在电子电路中用于测量电流的设备。在给定的规格书中,产品型号为C782062的电流采样电阻是Tc06-10-3.2,由深圳市业展电子有限公司生产。这款电阻采用跳线型设计,适用于需要精确...
《12306火车票抢票分流器Bypass-1.16.5:解析与应用指南》 12306火车票抢票分流器Bypass_1.16.5是一款针对中国铁路客户服务中心12306官网的辅助工具,旨在帮助用户在高峰期更高效地抢购火车票。这款软件的版本号为...
本文通过使用Fluent仿真软件,对简易型液体分流器进行内部流场分析,技术性地分析了分流器的压力场、速度场以及速度流线,并通过改变分流器结构,分析比较多个因素,得出了分流器的最佳结构设计。 Fluent软件是一种...
电动汽车中的分流器是一种至关重要的部件,它主要用于电池组主回路电流的精确检测,是电动汽车电池管理系统(BMS)的关键输入参数。分流器基于欧姆定律工作,通过在其两端测量电压来计算通过的电流,因此,电阻的...
网络分流器 TAP 网络分流器 TAP 是一种特殊的网络设备,能够在不中断网络正常流量的情况下,动态接入网络进行检测分析和流量访问。TAP 设备通常用于网络入侵检测系统(IPS)、网络探测器和分析器等领域。 TAP 工作...
TAP交换机、镜像交换机、汇聚分流器、盛科交换机、V530-TAP产品规格书 TAP交换机是网络流量监控和分析的关键设备之一,能够实时监控和复制网络流量,提供全面的网络可视化和分析功能。V530-TAP系列交换机是TAP...
建立了一种送风管道为等截面等风口的膜分离制氮装置分流器实验模型,旨在对分流器各出风孔口的分流进行问题分析与优化计算,通过对模型分风实验测定,得到了分流器各风口出风量大小不等的结果,其分风量的最大偏差为...