https://msdn.microsoft.com/en-us/library/eeah46xd.aspx
转自: //http://blog.csdn.net/zhuce0001/article/details/9152515.
在基于对话框的程序中,有一个任务是改变编辑框控件的背景,怎么办?
实现思路如下,子控件要绘制时会向父类(这里是主窗口)发送WM_CTLCOLOR
消息,在父类中(这里是主窗口)响应WM_CTLCOLOR,根据消息传递过来的
参数进行相应的操作,具体代码如下:
- CBrush m_brush;
- m_brush.CreateSolidBrush(RGB(0, 0, 255));
- HBRUSH CMy112Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
- {
- HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
- if (pWnd->GetDlgCtrlID() == IDC_EDIT1)
- {
- pDC->SetBkMode(TRANSPARENT);
- return m_brush;
- }
- return hbr;
- }
代码解释如下:在主对话框类CMy112Dlg中定义一个成员变量m_brush,并在主对话
框类中的构造函数中进行初始化。然后为父类编写WM_CTLCOLOR,在消息响应中判断
控件是否为要设置的编辑框控件(要设置的编辑框控件ID为IDC_EDIT1)将背景模式设
置为透明,并设置控件背景为蓝色。
这和消息反射有什么关系呢?上述代码有问题吗?上述方法也不失为一种好方法,但从
软件工程角度看还有一些缺憾,子类控件的消息都要父类去处理,这样就会导致父类
中的代码臃肿,而子类无事可做。另一方面,如果其它的工程要用到类似功能,怎么办?
只好把上述函数代码拷贝到另外工程中,并进行稍微修改。
MFC4.0开始有了解决此问题的一种新方法:消息反射,以上面为例,子控件要绘制时,
会向父类发送要绘制的消息,父类收到消息后,首先反射(再发给)给子控件,看子控件
是否对此消息做了处理,如果做了处理,父类将不再处理。如果子控件没有处理,则
父类对子控件发送的消息做处理。
再看一下上面例子的另一种方法:消息反射法
为工程添加一处新类CYellowEdit,此类从MFC的CEdit类派生,为类添加三个成员变量
- COLORREF m_clrText;
- COLORREF m_clrBkgnd;
- CBrush m_brBkgnd;
分别是文本颜色,背景色,画刷,在CYellowEdit类构造函数中进行初始化
- CYellowEdit::CYellowEdit()
- {
- m_clrText = RGB(0, 0, 0);
- m_clrBkgnd = RGB(255, 255, 0);
- m_brBkgnd.CreateSolidBrush(m_clrBkgnd);
- }
为CYellowEdit类添加反射函数(消息前面带有=的是反射消息,本例中为=WM_CTRLCOLR,
- HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor)
- {
- pDC->SetTextColor(m_clrText); // 文本颜色
- pDC->SetBkColor(m_clrBkgnd); // 背景色
- return m_brBkgnd; // 控件背景
- }
在主对话框上再添加一个编辑框,并为之关联变量,关联变量类型为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