当前位置:C++技术网 > 精选软件 > CEdit编辑框重载实现文字颜色、背景色和字体

CEdit编辑框重载实现文字颜色、背景色和字体

更新时间:2016-10-20 11:08:24浏览次数:1+次

    先来看看我们实现的效果图:

CEdit编辑框重载实现文字颜色、背景色和字体

【背景色,选择文字背景色,文字颜色,文字字体效果】

    我们处理WM_CTLCOLOR消息,就可以让控件改变文字和背景颜色。然而重载了CEdit后,我们发现处理WM_CTLCOLOR消息并不会被响应,更不会实现颜色的改变。
    为什么呢?我们在类视图中,右击,启动类向导,在消息标签下,可以看到两种消息,一个是=WM_CTLCOLOR,一个是WM_CTLCOLOR消息。自然,后一个是标准的消息,那么前者是什么鬼呢?
    而我们在重载CEdit的类中添加的WM_CTLCOLOR消息处理并不会生效。那么来看看=WM_CTLCOLOR。我们先同时添加两个消息的处理,然后在处理程序列表中如下图所示:
看看=WM_CTLCOLOR
    可以看到,标准的消息WM_CTLCOLOR的处理函数为OnCtlColor,而=WM_CTLCOLOR的处理函数为CtlColor。处理函数的名称区别在于On。MFC中,以On开头的处理函数,都是MFC预定义好的消息处理函数,可以被重载。在名称上并不能看出什么端倪。那么我们看看生成的函数的差别吧。
    生成的函数定义分别如下:
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("微软雅黑"));//创建字体
}

    那么其他控件的重载和消息处理,也大致可以参考这个方法,请举一反三。