改变控件的背景颜色和字体颜色

在默认情况下, 我们看到的对话框及其控件的背景和字体颜色都是浅灰色的,为了美化界面我们可以使用MFC中的WM_CTLCOLOR消息,它的响应函数是Cwnd类的OnCtlColor.。该函数声明如下:

afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor );

返回值:OnCtlColor必须返回一个刷子句柄,该刷子将被用于画出控件的背景。
参数:
pDC       指向当前要绘制的控件的DC指针。  
PWnd      指向当前要绘制的控件  
NCtlColor 指定了控件的类型: 
· CTLCOLOR_BTN        按钮控件  
· CTLCOLOR_DLG        对话框  
· CTLCOLOR_EDIT       编辑控件  
· CTLCOLOR_LISTBOX    列表框控件  
· CTLCOLOR_MSGBOX     消息框  
· CTLCOLOR_SCROLLBAR  滚动条控件  
· CTLCOLOR_STATIC     静态控件 
该函数的返回值是个画刷句柄,用于绘制指定控件的背景颜色。


控件绘制流程


当一个子控件将要被绘制时,它都会向它的父窗口(通常是对话框)发送一个WM_CTLCOLOR来准备一个设备上下文,以便使用正确的颜色来绘制该控件。如果想要改变控件上的文本颜色,可以在改函数中调用CDC类中的SetText函数来实现,改变字体背景颜色使用SetBKColor来实现,对应对话框对象来说,由于它是父窗口,会有多个子控件向它请求颜色设置,因此OnCtlColor函数会多次被调用。


在改变控件的背景颜色之前,我们需要先完成对话框的创建,然后在为创建的对话框添加类,后续的OnCtlColor函数就在这个类中响应,该函数的默认实现如下:

HBRUSH CDrawMainDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    
    //如果默认的不是所需画笔,则返回另一个画笔
    
    return hbr;
}
对应画刷对象转化为画刷句柄的过程分析“operator Hbrush”,我们在对话框类中添加私有类型的成员变量:m_brush,在构造函数中为其初始化为蓝色画刷,这个画刷就是我们自己定义的,代码如下:

m_brush.CreateSolidBrush(RGB(0,0,255))

改变整个对话框的及其子控件的背景颜色


代码如下:

HBRUSH CDrawMainDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

    //将hbr替换为我们自定义的画刷
    return m_brush;
}

运行效果:



改变某个控件的背景或文本颜色


如果我们只想改变某一类或者某个控件背景颜色的话,我们可以通过判断OnCtlColor响应函数中的第三个参数nCtlColor来判断当前的控件类型;若想修改某个具体的控件背景颜色和文本颜色,我们可以通过pWnd所指的类对象成员函数GetDlgCtrID来获得当前的控件ID,这里给出绘制某个具体控件的ID背景颜色和字体颜色,代码如下:

HBRUSH CDrawMainDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    
    int nCtrlID = pWnd->GetDlgCtrlID();
    switch (nCtrlID)
    {
    //静态文本控件
    case IDC_STATIC_TEST:
        pDC->SetTextColor(RGB(255,0,0)); //红色字体
        pDC->SetBkMode(TRANSPARENT);     //透明字体背景
        hbr = m_brush;                   //蓝色控件背景
    	break;
    //编辑框控件
    case IDC_EDIT:
        pDC->SetBkColor(RGB(0,255,0));  //绿色字体背景
        break;
    //单选框控件
    case IDC_RADIO_MATH:
        pDC->SetTextColor(RGB(0,255,0));  //绿色字体
        hbr = (HBRUSH)GetStockObject(DKGRAY_BRUSH);    //蓝色控件背景
        break;
    //复选框控件
    case IDC_CHECK_YES:
        pDC->SetTextColor(RGB(0,0,255));    //蓝色字体颜色
        pDC->SetBkColor(RGB(0,255,255));    //天蓝色字体背景
        break;
    case IDOK:
        pDC->SetTextColor(RGB(0,255,255));  //天蓝色字体
        hbr = m_brush;                      //蓝色控件背景
        break;
    default:
        break;
    }

    // 如果默认的不是所需画笔,则返回另一个画笔
    return hbr;
}
运行效果:




改变按压式的Button控件的背景颜色和字体颜色


我们发现对应按压式的button按钮,是不起作用的,而对于Radio Button可以起作用。如果我们想修改按钮式的button按钮外观,我们需要使用CButton类的一个成员函数DrawItem,该函数声明如下:

virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );
参数:

lpDrawItemStruct 指向结构DRAWITEMSTRUCT的一个长指针,该结构中记录了要绘制的项的信息以及绘制的风格。  
我们可以继承CButton类定义一个我们自己的类,在自定义类中需要重写DrawItem函数。通过DrawItem函数我们就可以绘制自定义按钮,
自定义的按钮的风格需要设置为BS_OWNERDRAW才能生效


使用步骤:

1.设置该Button控件的Owner draw选项,使之具备BS_OWNERDRAW风格。

2.将Button控件关联一个成员变量,类型为自定义的类。

3.可以在对话框的OnInitDialg函数中初始化成员变量,使之具备想要的外观。

我们将Button按钮关联为CButtonST类,并在该button未激活时将其设置成红色背景和蓝色字体颜色,该类在网络上可以找的类,具体设置代码如下:

BOOL CDrawMainDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    //编辑的显示字体
    m_Edit.SetWindowText("Hello World!");
    //按钮初始化
    m_btnST.SetInactiveFgColor(RGB(0,0,255), TRUE);
    m_btnST.SetInactiveBgColor(RGB(255,0,0), TRUE);
    return TRUE;  // return TRUE unless you set the focus to a control
    // 异常: OCX 属性页应返回 FALSE
}
运行效果:


对于部分的控件类型,使用MFC的消息反射技术,更加简单,关于消息反射的学习,在其他博文介绍,关于控件自绘4种技术和应用场景分析,参考“4种控件自绘技术分析

原文地址:https://www.cnblogs.com/jinxiang1224/p/8468352.html