一、消息反射处理流程图:
1、父窗口收到控制子窗口发来的通知消息后,调用它的虚函数CWnd::OnNotify.
CWnd::OnNotify()主体部分:
{
if (ReflectLastMsg(hWndCtrl, pResult)) //此时,hWndCtrl,为发送窗口,即子窗口的句柄
return TRUE; // 子窗口已处理了此消息
AFX_NOTIFY notify;
notify.pResult = pResult;
notify.pNMHDR = pNMHDR;
return OnCmdMsg(nID,MAKELONG(nCode, WM_NOTIFY), ¬ify, NULL);
}
分析:首先,调用ReflectLastMsg(hCtrlChildWnd,...)给子窗口一个自身处理的机会,将消息反射给子窗口处理,函数返回TRUE,表明子窗口处理了此消息。反之,表示子窗口未处理此消息,此时,调用OnCmdMsg(...)由父窗口进行通常的处理。
2、ReflectLastMsg中:
主要是调用发送窗口的SendChildNotifyLastMsg(...)。
3、SendChildNotifyLastMsg 中:
调用发送窗口的虚函数OnChildNotify函数,进行处理。 如果没有处理,则调用ReflectChildNotify(...)函数进行标准的反射消息的消息映射处理。
二、消息处理
方式1:
由上述处理流程可以看出来,子窗口要想自身处理此消息,重载子控件窗口的OnChildNotify虚拟函数应该是很容易想到的方式。
注意:MFC中对各个子控件窗口一般都已经重载了OnChildNotify函数,它对应调用类的虚函数进行处理,所以,你重载对应的虚函数即可,如下例:
BOOLCStatusBarCtrl::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam,LRESULT* pResult)
{
if (message != WM_DRAWITEM) //对应不同的控制,会有不同的有特殊处理要求的消息。
return CWnd::OnChildNotify(message, wParam, lParam, pResult);
...
...
DrawItem((LPDRAWITEMSTRUCT)lParam);
return TRUE;
}
virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );
voidCStatusBarCtrl::DrawItem(LPDRAWITEMSTRUCT)
{
ASSERT(FALSE); // must override for self draw status bars
}
你重载CStatusBarCtrl类的DrawItem虚拟函数,即可实现对反射消息WM_DRAWITEM的处理。
方式2:
从方式1可以看出,如果你不在被重载的OnChildNotify中对消息进行处理,函数会调用CWnd::OnChildNotify,它调用ReflectChildNotify函数进行标准的处理。
1、增加反射消息的映射入口。
2、增加对应的消息处理函数。
注意:可以使用MFC的ClassWizard作上述动作,在ClassWizard中,可处理的反射消息以一个=号以示区别。返回值为TRUE,表示控件窗口已处理此反射消息,为FALSE,表示控件子窗口未处理此反射消息。
结语:
消息反射不是很难的概念。它仅出现在MFC中;它的用意是方便控制子窗口的重用;对某些通知消息你可以重载对应的虚函数(WM_DRAWITEM...)进行处理;对其它你可以使用标准的消息反射映射进行处理。限于篇幅,一些细节问题,请阅读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. 神经系统的基本调节机制是反射,且反射的完成依赖于完整的反射弧。3. 如果反射弧中的任何部分缺失,反射活动将无法进行。例如,传出神经受损会导致即使有强烈刺激,人体也无法作出反应,因为效应器无法接收神经冲...
消息反射使用的一个例子
首先,我们创建一个基于对话框的工程,确保构建环境已准备好。接下来,使用向导功能创建一个名为CMyEdit的类,其基类为CEdit,这为后续的自定义控件打下基础。在CMyEdit的头文件中,我们定义了三个成员变量:COLORREF m_clrText、COLORREF m_clrBkgnd和CBrush m_brBkgnd,分别用于存储文本颜色、背景颜色...
初中物理知识点总结谁知道
1.反射角等于入射角,且入射光线与平面的夹角等于反射光线与平面的夹角。2.反射光线与入射光线居于法线两侧且都在同一个平面内。3.在光的反射现象中,光路是可逆的。 四、根据光的反射定律作光路图(常考知识点):先找出入射点,过入射点作垂直于界面的法线,则反射光线与入射光线的夹角的角平分线即为法线。若是...
生理学中反射的概念
反射在中枢神经系统参与下,机体对内外环境刺激所作出的规律性反应。反射活动的结构基础是反射弧。高等动物和人的反射有两种: 一种是在系统发育过程中形成并遗传下来,因而生来就有的先天性反射,称非条件反射。它是由于直接刺激感受器而引起的,通过大脑皮质下各中枢完成的反射。另一种是条件反射,是...
初中知识点:光的反射定律
一、光的反射基础光的反射,这一看似简单的光学现象,实则蕴含着丰富的物理原理。当光线在不同介质界面发生改变并返回原介质时,我们就称之为光的反射。遵循的三大法则,“三线共面”(反射光线、入射光线和法线在同一平面上)、“两线分居”(反射光线与入射光线分居法线两侧)和“两角相等”(反射角等于...
反射弧:反射活动的结构基础是什么?
例如,膝跳反射的中枢位于腰脊髓,而更为复杂的生理功能,如呼吸调节,涉及延髓、脑桥、下丘脑甚至大脑皮层的广泛协作。延髓,这个至关重要的区域,不仅启动基本的呼吸活动,还与更高层次的神经元群共同调节,赋予生命适应环境的灵活性。感受野,则为我们揭示了反射活动的精确指向,特定的感受器对特定刺激的...
什么是条件反射
1、条件反射理论是巴甫洛夫的高级神经活动学说的核心理论,指在一定条件下,外界刺激与有机体反应之间建立起的暂时神经联系。后天形成,有经典条件反射和操作性条件反射两种形式。非条件反射是条件反射形成的基础。2、条件反射在解剖生理学上又称前馈把控系统。两样没有任何联系的东西,因为长期一起出现,...
心理咨询师考点:高级神经系统的反射学说
②条件反射:通过模仿、学习,在无条件反射的基础上 ③巴甫洛夫为经典条件反射,如酸梅、被蛇咬。斯金纳叫操作性或工具条件反射。如马戏团的动物、大白学会走迷宫、大白在斯金纳箱里按压杠杆(共同特点是都有操作或经过训练)。2、基本规律 (1)条件反射的.抑制:外抑制:额外刺激的出现使条件反射停止反应。