王朝网络
分享
 
 
 

深度剖析消息反射机制

王朝vc·作者佚名  2006-01-08
宽屏版  字体: |||超大  

摘要:在前面我们分析了控件通知消息WM_NOTIFY,和WM_NOTIFY紧密联系的还有一个MFC新特性:消息反射。本文中,我想就这个问题作一个全面的论述,如果有错误,还望各路大虾批评指正。

什么是消息反射?

在windows里面,子控件经常向父控件发送消息,例如很多子控件要绘制自己的背景,就可能向父窗口发送消息WM_CTLCOLOR。对于从子控件发来的消息,父控件有可能在处理之前,把消息返还给子控件处理,这样消息看起来就想是从父窗口反射回来一样,故此得名:消息反射。

消息反射的由来

在windows和MFC4.0版本一下,父窗口(通常是一个对话框)会对这些消息进行处理,换句话说,自控件的这些消息处理必须在父窗口类体内,每当我们添加子控件的时候,就要在父窗口类中复制这些代码,我们可以想象这是多么的复杂,代码是多么的臃肿!

我们可以想象,如果这些消息都让父窗口类去做,父窗口就成了一个万能的神,一个臃肿不堪的代码机,无论如何消息的处理都集中在父窗口类中,会使父窗口繁重无比,但是子控件却无事可做,并且代码也无法重用,这对于一个程序员来讲是多么痛苦的一件事?!

在老版本的MFC中,设计者也意识到了这个问题,他们对一些消息采用了虚拟机制,例如:WM_DRAWITEM,这样子控件就有机会控制自己的动作,代码的可重用性有了一定的提高,但是这还没有达到大部分人的要求,所以在高版本的MFC中,提出了一种更方便的机制:消息反射。

通过消息反射机制,子控件窗口便能够自行处理与自身相关的一些消息,增强了封装性,同时也提高了子控件窗口类的可重用性。不过需要注意的是:消息反射是MFC实现的,不是windows实现的;要让你的消息反射机制工作,你得类必须从CWnd类派生。

Message-Map中的处理

如果想要处理消息反射,必须了解相应的Message-Map宏和函数原型。一般来讲,Message-Map是有一定的规律的,通常她在消息的前面加上一个ON_ ,然后再消息的最后加上 _REFLECT。例如我们前面提到的WM_CTLCOLOR 经过处理后变成了ON_WM_CTLCOLOR_REFLECT;WM_MEASUREITEM则变成了ON_WM_MEASUREITEM_REFLECT。

凡事总会有例外,这里也是这样,这里面有3个例外:

(1) WM_COMMAND 转换成 ON_CONTROL_REFLECT;

(2) WM_NOTIFY 转换成 ON_NOTIFY_REFLECT;

(3) ON_UPDATE_COMMAND_UI 转换成 ON_UPDATE_COMMAND_UI_REFLECT;

对于函数原型,也必须是以 afx_msg 开头。

利用ClassWizard添加消息反射

(1)在ClassWizard中,打开选择项Message Maps;

(2)在下拉列表Class name中选择你要控制的类;

(3)在Object IDs中,选中相应的类名;

(4)在Messages一栏中找到前面带有=标记的消息,那就是反射消息;

(5)双击鼠标或者单击添加按钮,然后OK!

消息处理的过程

(1)子窗口向父窗口发送通知消息,激发父窗口去调用它的虚函数CWnd::OnNotify。大致的结构如下

BOOL CWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)

{

if (ReflectLastMsg(hWndCtrl, pResult)) file://hWndCtrl,为发送窗口

return TRUE; file://如果子窗口已处理了此消息,返回

AFX_NOTIFY notify;

notify.pResult = pResult;

notify.pNMHDR = pNMHDR;

return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY)? notify:NULL);

}

(2)ReflectLastMsg声明如下:static BOOL PASCAL ReflectLastMsg(HWND hWndChild, LRESULT* pResult = NULL);

它的主要任务就是调用发送窗口的SendChildNotifyLastMsg。

(3)SendChildNotifyLastMsg声明如下:BOOL SendChildNotifyLastMsg(LRESULT* pResult = NULL);

调用发送窗口的虚函数OnChildNotify函数,进行处理。 如果发送窗口没有进行重载处理,则调用ReflectChildNotify(...)函数进行标准的反射消息的消息映射处理。

使用的一个例子

这里面我们举一个简单的例子,希望大家能够更清晰的掌握消息反射机制。

(1)创建一个基于对话框的工程。

(2)利用向导创建一个新的类:CMyEdit,基类是CEdit。

(3)在CMyEdit头文件中加入3个成员变量:

COLORREF m_clrText ;

COLORREF m_clrBkgnd ;

CBrush m_brBkgnd;

(4)利用向导在其中加入WM_CTLCOLOR(看到了么,前面是不是有一个=?),并且将它的函数体改为:

HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor)

{

pDC->SetTextColor( m_clrText ); // text

pDC->SetBkColor( m_clrBkgnd ); // text bkgnd

return m_brBkgnd; // ctl bkgnd

}

同时我们在.cpp文件中会看到ON_WM_CTLCOLOR_REFLECT(),这就是我们所说的经过处理的宏,是不是很符合规则?

(5)在对话框中加入一个Edit,增加一个关联的变量,选择Control属性,类别为CMyEdit。

(6)在对话框.cpp文件中加入#include "MyEdit.h",运行,看到了什么?呵呵。

事情到了一个阶段,希望你能够喜欢,明天见!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有