【背景色,选择文字背景色,文字颜色,文字字体效果】
我们处理WM_CTLCOLOR消息,就可以让控件改变文字和背景颜色。然而重载了CEdit后,我们发现处理WM_CTLCOLOR消息并不会被响应,更不会实现颜色的改变。为什么呢?我们在类视图中,右击,启动类向导,在消息标签下,可以看到两种消息,一个是=WM_CTLCOLOR,一个是WM_CTLCOLOR消息。自然,后一个是标准的消息,那么前者是什么鬼呢?
而我们在重载CEdit的类中添加的WM_CTLCOLOR消息处理并不会生效。那么来看看=WM_CTLCOLOR。我们先同时添加两个消息的处理,然后在处理程序列表中如下图所示:
生成的函数定义分别如下:
HBRUSH CEditMoney::CtlColor(CDC* pDC, UINT nCtlColor)
{
// TODO: 在此更改 DC 的任何特性
// TODO: 如果不应调用父级的处理程序,则返回非 null 画笔
//return NULL;
}
HBRUSH CEditMoney::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CEdit::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何特性
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return hbr;
}
CtlColor函数没有窗口指针参数。两个函数返回值一样,其他参数一样。也就是说,在处理上,基本差不多,只是有些细节上的区别。
我们再进一步看看消息映射的差别,下面是自动生成的消息映射:
BEGIN_MESSAGE_MAP(CEditMoney, CEdit)
ON_WM_CHAR()
ON_WM_CTLCOLOR_REFLECT()
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
从这里,就可以一眼看出差别了。ON_WM_CTLCOLOR()是WM_CTLCOLOR的消息处理函数映射,这是标准的。那么ON_WM_CTLCOLOR_REFLECT()自然就是=WM_CTLCOLOR消息处理映射了。我们可以看到后面的REFLECT,这个一个细节已经说明了所有的差别。
REFLECT是反射的意思。就像镜子反射阳光一样。这里需要做一个背景知识的介绍。
对话框中的控件,很多消息是不会自己直接处理的,而是依赖父窗口处理。所以,如果我们直接用CEdit处理编辑框,WM_CTLCOLOR消息就是直接在父窗口类中处理的。此时我们并不能很好的定制一个控件。我们定制的控件是在我们自己写的控件类里对消息进行处理,而不是依赖父窗口的处理。
我们开始遇见的,在重载类中处理WM_CTLCOLOR并没有用,原因是这个消息并不会直接由控件接受,而是父窗口接受到的。默认情况下,父窗口接受到WM_CTLCOLOR消息,就会对控件进行绘制。所以,消息没有到控件里来,自然我们在重载的控件类里也无法处理这个消息。
MFC想到的一个机制就是将这个消息反射到控件类里。也就是增加的等号加上消息这类消息,这里就是=WM_CTLCOLOR,消息映射是ON_WM_CTLCOLOR_REFLECT()。此时父窗口接受到WM_CTLCOLOR后,会将此消息转发给对应的控件处理,这里也就是执行了CEditMoney::CtlColor函数。而消息处理逻辑就和CEditMoney::OnCtlColor差不多。差别的原因就在于消息的来源不同。
所以要让CEdit编辑框重载实现文字颜色、背景色和字体,只要处理=WM_CTLCOLOR就好了。下面是处理代码:
HBRUSH CEditMoney::CtlColor(CDC* pDC, UINT nCtlColor)
{
// TODO: 在此更改 DC 的任何特性
pDC->SetTextColor(RGB(255,0,0));//文字颜色
pDC->SetBkColor(RGB(230,230,230));//文字背景颜色
pDC->SelectObject(&m_font);//应用预先创建好的字体
// TODO: 如果不应调用父级的处理程序,则返回非 null 画笔
return (HBRUSH)m_brush.m_hObject;//设置背景颜色
//return NULL;
}
因为设置的字体要一直有效,所以要用类成员变量来保存,背景画刷也如此。这两个变量都在构造函数里创建字体和画刷。代码如下:
CEditMoney::CEditMoney()
{
m_brush.CreateSolidBrush(RGB(0,255,255));//创建背景画刷
m_font.CreatePointFont(90,_T("微软雅黑"));//创建字体
}
那么其他控件的重载和消息处理,也大致可以参考这个方法,请举一反三。