文章参考地址:http://blog.csdn.net/hisinwang/article/details/8070393

        在每个控件开始绘制之前,都会向其父窗口发送WM_CTLCOLOR通告消息,在该消息的处理函数中,可以设置控件显示文本的前景色、背景色以及字体。该消息处理函数还要求返回一个画刷的句柄,用于在控件具体的绘制之前擦除其客户区。

        WM_CTLCOLOR映射消息处理函数为afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)。
        常用代码为:

pDC->SetTextColor(RGB(255, 0, 0));    //设置文本前景色
pDC->SetBkColor(RGB(255, 255, 255)); //设置文本背景色
pDC->SetBkMode(TRANSPARENT); //TRANSPARENT或OPAQUE
pDC->SelectObject(...)

       简单示例如下:

//
//m_font1与m_font2为CTestDlg的成员,类型为CFont
//
BOOL CTestDlg::OnInitDialog()
{
......
// TODO: Add extra initialization here
m_font1.CreatePointFont(120, TEXT("Impact"));
m_font2.CreatePointFont(120, TEXT("Arial"));
......
} HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes of the DC here
if (nCtlColor == CTLCOLOR_STATIC)
{
switch (pWnd->GetDlgCtrlID())
{
case IDC_STATIC_1:
pDC->SetTextColor(RGB(255, 0, 0));
pDC->SetBkColor(RGB(255, 255, 255));
pDC->SetBkMode(TRANSPARENT);
pDC->SelectObject(&m_font1);
return (HBRUSH)::GetStockObject(BLACK_BRUSH);
break;
case IDC_STATIC_2:
pDC->SetTextColor(RGB(255, 255, 0));
pDC->SetBkColor(RGB(255, 255, 255));
pDC->SelectObject(&m_font2);
return (HBRUSH)::GetStockObject(BLACK_BRUSH);
break;
default:
break;
}
} // TODO: Return a different brush if the default is not desired
return hbr;
}


 说明一:
OnCtlColor中的nCtlColor可为:
CTLCOLOR_BTN   Button control

CTLCOLOR_DLG   Dialog box

CTLCOLOR_EDIT   Edit control

CTLCOLOR_LISTBOX   List-box control

CTLCOLOR_MSGBOX   Message box

CTLCOLOR_SCROLLBAR   Scroll-bar control

CTLCOLOR_STATIC   Static control

        可见,WM_CTLCOLOR可作用于按钮控件CButton、编辑框控件CEdit、ListBox控件、Static控件、滚动条控件,也可作用于对话框本身。

        注意:前面讲WM_CTLCOLOR为通告消息,也即是子控件发送给父窗口的,但对于对话框本身,它能收到nCtlColor为CTLCOLOR_DLG的WM_CTLCOLOR消息,这是自身发给自身的,显然,这时不是通告消息。

示例:

HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes of the DC here
if (nCtlColor == CTLCOLOR_DLG)
return (HBRUSH)::GetStockObject(BLACK_BRUSH);
else
pDC->SetTextColor(RGB(255, 0, 0)); // TODO: Return a different brush if the default is not desired
return hbr;
}


    说明二
    OnCtlColor消息里面的处理对PushButton是不起作用的,由说明一中的示例效果也可以看出,而对CheckBox和RadioButton是OK的。附上CSDN给出的解释:
Buttons with the BS_PUSHBUTTON, BS_DEFPUSHBUTTON, or BS_PUSHLIKE styles do not use the returned brush. Buttons with these styles are always drawn with the default system colors. Drawing push buttons requires several different brushes-face, highlight, and shadow-but the WM_CTLCOLORBTN message allows only one brush to be returned. To provide a custom appearance for push buttons, use an owner-drawn button.
所以,对PushButton只能将其设置为owner-drawn button,然后响应控件通告消息WM_DRAWITEM来处理,该消息的响应函数原型为afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)。

    说明三:对ComboBox控件的应用
    ComboBox控件包含一个EditBox,当单击展开的时候,会出现一个ListBox列出所有的项目,注意,这时ListBox控件的父窗口不是这个ComboBox,而是ComboBox的父窗口。
所以,如果要在代码中设置某个ComboBox所显示文字的字体颜色为红色(EditBox以及下拉ListBox中的文字),假设该ComboBox的ID为IDC_COMBO,则使用如下代码将无任何作用。
if (pWnd->GetDlgCtrlID() == IDC_COMBO)
{
pDC->SetTextColor(RGB(255, 0, 0));
}

EditBox以及下拉ListBox中的文字颜色均没有改变。
    以下对话框中有两个ComboBox控件m_combo1,m_combo2。现要使m_combo1中显示的文字颜色为红色,而m_combo2为默认。代码如下
HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes of the DC here //对m_combo1的EditBox(该EditBox的父窗口为m_combo1)
if (nCtlColor == CTLCOLOR_EDIT
&& pWnd->GetParent()->GetDlgCtrlID() == m_combo1.GetDlgCtrlID())
{
pDC->SetTextColor(RGB(255, 0, 0));
} //对m_combo1下拉的ListBox
if (nCtlColor == CTLCOLOR_LISTBOX
&& m_combo1.GetParent()->GetDlgCtrlID() == pWnd->GetParent()->GetDlgCtrlID())
{
//获取ListBox和m_combo1的屏幕坐标范围
RECT rectListBox;
RECT rectComboBox;
pWnd->GetWindowRect(&rectListBox);
m_combo1.GetWindowRect(&rectComboBox);
//如果该ListBox刚好在m_combo1的下面,则是单击m_combo1产生的下拉ListBox
if (rectListBox.left == rectComboBox.left
&& rectListBox.top == rectComboBox.bottom)
{
pDC->SetTextColor(RGB(255, 0, 0));
}
} // TODO: Return a different brush if the default is not desired
return hbr;
}

效果如下:

    更简单的办法是:利用向导新增MFC类CMyComboBox : CComboBox,再增加WM_CTLCOLOR消息的响应函数。(注意:ComboBox下的EditBox和ListBox均会向ComboBox窗口发送WM_CTLCOLOR消息,如果在ComboBox对应的消息映射表没有找到对应的处理函数,再向CComboBox的父窗口发送WM_CTLCOLOR消息,具体可参考文章WM_NOTIFY消息流程实例分析
BEGIN_MESSAGE_MAP(CMyComboBox, CComboBox)
ON_WM_CTLCOLOR()
END_MESSAGE_MAP() HBRUSH CMyComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes of the DC here
pDC->SetTextColor(RGB(255, 255, 0)); // TODO: Return a different brush if the default is not desired
return hbr;
}

pDC->SetTextColor(RGB(255, 255, 0));一句代码就可以实现上面的功能。

    说明四、WM_CTLCOLOR为通告消息,所以也可以在反射消息中处理。
ON_WM_CTLCOLOR_REFLECT()

WM_CTLCOLOR消息的更多相关文章

  1. 【转】MFC WM_CTLCOLOR 消息

    WM_CTLCOLOR消息用来完成对EDIT, STATIC, BUTTON等控件设置背景和字体颜色, 其用法如下: 1.首先在自己需要设置界面的对话框上点击右键-->建立类向导-->加入 ...

  2. WM_INITDIALOG与WM_CREATE消息的区别

      WM_CREATE是所有窗口都能响应的消息,表明本窗口已经创建完毕(可以安全的使用这个窗口了,例如在它上面画控件等).在响应WM_CREATE消息响应函数的时候,对话框及子控件还未创建完成,亦是说 ...

  3. MFC程序中消息以及函数的处理顺序简介[转]

    MFC应用程序中处理消息的顺序 1.AfxWndProc()      该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc()  该 ...

  4. Windows消息编程(写的不错,有前因后果)

    本文主要包括以下内容: 1.简单理解Windows的消息2.通过一个简单的Win32程序理解Windows消息3.通过几个Win32程序实例进一步深入理解Windows消息4.队列消息和非队列消息5. ...

  5. MFC消息顺序

    1.AfxWndProc()      该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc()  该函数负责保存消息(保存的内容主要 ...

  6. MFC消息机制

    何谓消息.消息处理函数.消息映射?消息简单的说就是指通过输入设备向程序发出指令要执行某个操作.具体的某个操作是你的一系列代码.称为消息处理函数. 在SDK中消息其实非常容易理解,当窗口建立后便会有一个 ...

  7. MFC窗口创建、销毁消息流程

    MFC应用程序创建窗口的顺序 1.PreCreateWindow()该函数是一个重载函数,在窗口被创建前,可以在该重载函数中改变创建参数,(可以设置窗口风格等等) 2.PreSubclassWindo ...

  8. MFC消息循环

    MFC消息循环 MFC应用程序中处理消息的顺序 1.AfxWndProc()  该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc. 2.AfxCallWndProc ...

  9. MFC中对话框的各种消息触发时间

    小结:WM_CREATE是所有窗口都能响应的消息,表明本窗口已经创建完毕.可以安全的使用这个窗口了,例如在它上面画控件等等.这个状态肯定是在调用ShowWindows()显示窗口之前.WM_WM_IN ...

随机推荐

  1. linux文件操作篇 (二) 打开和关闭文件

    2.1 打开文件和关闭文件 #include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>  头文件 i ...

  2. go学习笔记-面向对象(Methods, Interfaces)

    面向对象(Methods, Interfaces) Method method是附属在一个给定的类型上的,他的语法和函数的声明语法几乎一样,只是在func后面增加了一个receiver(也就是meth ...

  3. Angularjs+bootstrap 实现横向滑屏

    本地环境: AngularJS v1.3.2 angular-ui-bootstrap Version: 0.12.0 - 2014-11-16 实现代码:Html部分 <div ng-cont ...

  4. oracle查询优化,存储过程select表循环插入另一个表,以及索引重建

    查询语句pl/sql中用F5优化语句 ORACLE的explain plan工具的作用只有一个,获取语句的执行计划1.语句本身并不执行,ORACLE根据优化器产生理论上的执行计划2.语句的分析结果存放 ...

  5. vs2013中将复制过来的文件或文件夹显示到解决方案管理

    先将文件夹和文件复制到VS程序所在的位置,在VS2013解决方案资源管理器中找到这些文件所在的上一级文件夹,先将那个上层文件夹收缩起来,然后再点击解决方案资源管理器上的“显示所有文件”按纽,展开这个文 ...

  6. C++11中Lambda的使用

    Lambda functions: Constructs a closure, an unnamed function object capable of capturing variables in ...

  7. LeetCode:11. ContainerWithWater(Medium)

    原题链接:https://leetcode.com/problems/container-with-most-water/description/ 题目要求:给定n个非负整数a1,a2,...,an  ...

  8. 在Linux中安装和配置OpenVPN Server的最简便方法!

    本文介绍了如何在基于RPM和DEB的系统中安装和配置OpenVPN服务器.我们在本文中将使用一个名为openvpn-install的脚本,它使整个OpenVPN服务器的安装和配置过程实现了自动化.该脚 ...

  9. node 发送 post 请求 get请求。

    因为我们部门打算用node请求restful 然后慢慢替换掉服务端,以后直接请求soa的接口,让前端的数据更贴切项目,因为我们服务端接口和app公用一套,由于业务的需求和版本不统一(例如app6.4的 ...

  10. 「暑期训练」「基础DP」 Monkey and Banana (HDU-1069)

    题意与分析 给定立方体(个数不限),求最多能堆叠(堆叠要求上方的方块严格小于下方方块)的高度. 表面上个数不限,问题是堆叠的要求决定了每个方块最多可以使用三次.然后就是对3n" role=& ...