windows消息分析器的实现很好理 解,windows操作系统使用消息处理机制,那么,我们所设计的程序如何才能分辨和处理系统中的各种消息呢?这就是消息分析器的作用.

简单来说,消息分析器就是一段代码,在我的讲述中,将分7重来循序渐进的介绍它.从最初的第1重到最成熟的第7重,它的样子会有很大的变化.但,实现的功 能都是一样的,所不同的,仅仅是变得更加简练罢了.

程序开始时候,是WinMain函数,然后会生成初始的窗口,同时会调用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(小写和大写形式)
       ussigned 无符号数时,可在后面加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))));
}

至此,消息分析器,就介绍完毕。

转载于:https://blog.51cto.com/hantayi/336534

消息分流器-HANDLE_MSG相关推荐

  1. Windows消息分流器

    Windows消息循环讲的比较好的一篇博文 原谅链接: http://blog.csdn.net/hopkins9961629/article/details/588184 windows操作系统使用 ...

  2. windows应用程序-音乐播放器【一】

    源代码到girhub下载https://github.com/viafcccy/DoublePigMusicPlayer 消息分流器 HANDLE_MSG宏,需要引用<windowsx.h> ...

  3. Windows消息机制详解

    消息是指什么?      消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用 ...

  4. Windows消息机制详解-6

    消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用程序某个事情发生了.例如, ...

  5. Windows消息机制详解-2

    消息是指什么?      消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用 ...

  6. 【转】深入理解Windows消息机制

    转自:https://blog.csdn.net/liulianglin/article/details/14449577 今天我们来学一学Windows消息机制,我们知道在传统的C语音程序中,当我们 ...

  7. Windows消息机制概述

    消息是指什么?      消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用 ...

  8. chHANDLE_DLGMSG(windows核心编程)讲解

    看完<Windows程序设计>后开始看<windows核心编程>, 结果看第一个案例的时候就很惊人的发现,Jeffery大牛的代码很深奥.乍一看好像没有包含<window ...

  9. MFC消息处理学习总结

    Windows消息机制概述 http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html 消息是指什么?      消息系统对于一个win ...

  10. windowsx.h头文件使用说明

    windowsx.h头文件:(全部都是网上查的) http://www.codeproject.com/win32/msgcrackwizard.asp 第一部分: 介绍: WINDOWSX.H 头文 ...

最新文章

  1. 【CV】吴恩达机器学习课程笔记 | 第1-2章
  2. Codeforces Round #699 (Div. 2) F - AB Tree(贪心、树上DP)超级清晰,良心题解,看不懂来打我 ~
  3. captcha.js一个生成验证码的插件,使用js和canvas生成
  4. Java 8 - 07 复合 Lambda 表达式
  5. ExtJS4.2学习(9)——MVC
  6. Ctr点击率预估理论基础及项目实战
  7. 玩转oracle 11g(36):rman备份-控制文件丢失恢复
  8. 神经网络与深度学习——TensorFlow2.0实战(笔记)(二)(开发环境介绍)
  9. 实时获取滚动条的高度_适用于星上快速处理的雷达高度计有效波高反演技术
  10. 如何将android连接到pc,如何将Android屏幕镜像到PC
  11. 2018年最新整理ios APP审核被拒的常见原因
  12. c html中让图片反色,图片反色.html
  13. 设计模式之组合模式-树形结构的处理
  14. 在线考试系统html源码,jQuery在线答题考试系统代码
  15. [WDS] Disconnected解决方法
  16. 微信棋牌源码虚拟机搭建Hadoop集群
  17. 魔与道java版本_魔与道360版下载
  18. 最牛的商业模式,化肥厂利用买化肥送车,一年总利润600多万?
  19. 关于预答辩研究生汇报内容及方式的几点要求
  20. python语言使用不需要付费不存在商业风险_python+-中国大学mooc-题库零氪

热门文章

  1. 卢卡奇总体性原则_重识青年卢卡奇的“历史”概念问题
  2. Wireshark实战分析之TCP协议(三)
  3. IPSEC 002 ---- Internet危机四伏,IPSec闪亮登场
  4. H - 命运(动态规划) 数塔问题
  5. html+css网页设计源码_【技术篇前端】用html+css实现简化版孙膑kpl皮肤页面(内含源码)...
  6. excel取整数的函数_Excel教程:取整函数INT 与TRUNC~~Excel新技能
  7. Flink流式计算在节省资源方面的简单分析
  8. OpenCV图像处理基础操作(1)
  9. php入门案例,thinkphp3.2.1入门之--简单案例实现
  10. idean中jsp页面乱码_IntelliJ IDEA 控制台 乱码 有效解决办法