Message Reflection for Windows Controls(消息反射机制)

时间:2022-10-26 21:37:05

https://msdn.microsoft.com/en-us/library/eeah46xd.aspx

转自: //http://blog.csdn.net/zhuce0001/article/details/9152515.

在基于对话框的程序中,有一个任务是改变编辑框控件的背景,怎么办?

实现思路如下,子控件要绘制时会向父类(这里是主窗口)发送WM_CTLCOLOR

消息,在父类中(这里是主窗口)响应WM_CTLCOLOR,根据消息传递过来的

参数进行相应的操作,具体代码如下:

 

[cpp]  view plain  copy
 
  1. CBrush m_brush;  

 

[cpp]  view plain  copy
 
  1. m_brush.CreateSolidBrush(RGB(0, 0, 255));  

 

[cpp]  view plain  copy
 
  1. HBRUSH CMy112Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)   
  2. {  
  3.     HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);  
  4.       
  5.     if (pWnd->GetDlgCtrlID() == IDC_EDIT1)  
  6.     {  
  7.         pDC->SetBkMode(TRANSPARENT);  
  8.         return m_brush;  
  9.     }  
  10.   
  11.     return hbr;  
  12. }  


代码解释如下:在主对话框类CMy112Dlg中定义一个成员变量m_brush,并在主对话

 

框类中的构造函数中进行初始化。然后为父类编写WM_CTLCOLOR,在消息响应中判断

控件是否为要设置的编辑框控件(要设置的编辑框控件ID为IDC_EDIT1)将背景模式设

置为透明,并设置控件背景为蓝色。

这和消息反射有什么关系呢?上述代码有问题吗?上述方法也不失为一种好方法,但从

软件工程角度看还有一些缺憾,子类控件的消息都要父类去处理,这样就会导致父类

中的代码臃肿,而子类无事可做。另一方面,如果其它的工程要用到类似功能,怎么办?

只好把上述函数代码拷贝到另外工程中,并进行稍微修改。

MFC4.0开始有了解决此问题的一种新方法:消息反射,以上面为例,子控件要绘制时,

会向父类发送要绘制的消息,父类收到消息后,首先反射(再发给)给子控件,看子控件

是否对此消息做了处理,如果做了处理,父类将不再处理。如果子控件没有处理,则

父类对子控件发送的消息做处理。

再看一下上面例子的另一种方法:消息反射法

为工程添加一处新类CYellowEdit,此类从MFC的CEdit类派生,为类添加三个成员变量

 

[cpp]  view plain  copy
 
  1. COLORREF m_clrText;  
  2. COLORREF m_clrBkgnd;  
  3. CBrush   m_brBkgnd;  

分别是文本颜色,背景色,画刷,在CYellowEdit类构造函数中进行初始化

 

 

[cpp]  view plain  copy
 
  1. CYellowEdit::CYellowEdit()  
  2. {  
  3.     m_clrText = RGB(0, 0, 0);  
  4.     m_clrBkgnd = RGB(255, 255, 0);  
  5.     m_brBkgnd.CreateSolidBrush(m_clrBkgnd);  
  6. }  

为CYellowEdit类添加反射函数(消息前面带有=的是反射消息,本例中为=WM_CTRLCOLR,

 

 

[cpp]  view plain  copy
 
  1. HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor)   
  2. {  
  3.     pDC->SetTextColor(m_clrText);    // 文本颜色  
  4.     pDC->SetBkColor(m_clrBkgnd);     // 背景色  
  5.     return m_brBkgnd;                // 控件背景  
  6. }  

在主对话框上再添加一个编辑框,并为之关联变量,关联变量类型为CYelloEdit,运行程序可

 

以看到编辑框的背景已变成黄色了。

这就是消息反射的一个用处,使用消息反射和不使用消息反射这两个例子有什么区别呢?个

人认为最大的区别就是代码的可重用性,使用消息反射后,如果碰到类似应用,直接将

CYellowEdit拷贝到其它工程直接应用,不需要修改代码。

 

上述例子在MSDN中有详细介绍,在MSDN中主题为:ON_NOTIFY_REFLECT,

里面有一篇

TN062: Message Reflection for Windows Controls

的文章专门讲述了消息反射。网上也有不少这方面的文章,但基本上都是参考MSDN翻译的,

 

下面给出几个消息反射资料的博文地址

1    http://blog.csdn.net/gao_zilai/article/details/7417690

2    http://blog.csdn.net/cay22/article/details/6171616

3    http://bbs.ednchina.com/BLOG_ARTICLE_1926378.HTM