用MFC设计界面程序,界面风格和色彩比较单一,因为修改控件的字体和背景颜色都是一件麻烦的事。但是MFC作为C++的封装类,在计算方面有优势。
最近用MFC在开发一个采集下位机运行参数的上位机程序,对于报警和故障信息要进行突出显示,所以就打算通过改变静态文本控件(Text-Control)的背景颜色予以实现,即当有某种报警或故障出现时,对应的控件就变为红色,报警或故障消失时控件恢复为白色。这个计划应该比较合理,肯定可以实现。但在实现的过程中碰到不了少问题,譬如控件的背景颜色和文字颜色不是控件本身的属性,修改控件的背景颜色需要动用WM_CTLCOLOR消息来实现,在要更改颜色的时候需要向对话框发送WM_CTLCOLOR消息,这个消息主要在窗口重绘的时候触发,如在程序启动时和窗口最小化后再次展现等情况下需要绘制窗口。父窗口收到WM_CTLCOLOR消息会调用被重载了的OnCtlColor函数,它是由MFC类库的CWnd类的成员函数,该函数会返回一把画刷,用于重绘窗口中的控件。OnCtlColor函数原型如下:
afx_msg HBRUSH OnCtlColor(CDC *pDC,CWnd *pWnd,UINT nCtlColor);
参数说明(摘自msdn 文档Cwnd::OnCtlColor:http://msdn.microsoft.com/en-us/library/0wwk06hc(v=vs.100).aspx)
pDC Contains a pointer to the display context for the child window. May be temporary. pWnd Contains a pointer to the control asking for the color. May be temporary. nCtlColor 可取下述值之一,用于指定控件类型 CTLCOLOR_BTN 按键控件 CTLCOLOR_DLG 对话框 CTLCOLOR_EDIT 编辑框控件 CTLCOLOR_LISTBOX 列表框控件 CTLCOLOR_MSGBOX 消息框 CTLCOLOR_SCROLLBAR 滚动条控件 CTLCOLOR_STATIC 静态文本控件函数返回值
OnCtlColor must return a handle to the brush that is to be used for painting the control background. 这个函数必须返回操作绘制控件背景刷的句柄。
函数概要
The framework calls this member function when a child control is about to be drawn.
Most controls send this message to their parent (usually a dialog box) to prepare the pDC for drawing the control using the correct colors.
To change the text color, call the SetTextColor member function with the desired red, green, and blue (RGB) values.
To change the background color of a single-line edit control, set the brush handle in both the CTLCOLOR_EDIT and CTLCOLOR_MSGBOX message codes, and call the CDC::SetBkColor function in response to the CTLCOLOR_EDIT code.
Note:This member function is called by the framework to allow your application to handle a Windows message. The parameters passed to your function reflect the parameters received by the framework when the message was received. If you call the base-class implementation of this function, that implementation will use the parameters originally passed with the message and not the parameters you supply to the function. To add the following method to your dialog class, use the Visual Studio properties pane to add a message handler for WM_CTLCOLOR. Alternatively, you can manually add an ON_WM_CTLCOLOR() entry to the message map.
官方给出的例子
// This OnCtlColor handler will change the color of a static control // with the ID of IDC_MYSTATIC. The code assumes that the CPenWidthsDlg // class has an initialized and created CBrush member named m_brush. // The control will be painted with red text and a background // color of m_brush. HBRUSH CPenWidthsDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor){ // Call the base class implementation first! Otherwise, it may // undo what we're trying to accomplish here. HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); // Are we painting the IDC_MYSTATIC control? We can use // CWnd::GetDlgCtrlID() to perform the most efficient test. if (pWnd->GetDlgCtrlID() == IDC_MYSTATIC) { // Set the text color to red pDC->SetTextColor(RGB(255, 0, 0)); // Set the background mode for text to transparent // so background will show thru. pDC->SetBkMode(TRANSPARENT); // Return handle to our CBrush object hbr = m_brush; } return hbr;}
给对话框类添加WM_CTLCOLOR消息的响应函数On_CtlColor方法:
在工程(Project)菜单下选择类向导(Class Wizard),打开类向导对话框,选择消息(message)选项卡,找到WM_CTLCOLOR消息选项,点击添加handler按键,即加入了WM_CTLCOLOR响应函数,在响应函数On_CtlColor中编写代码即可。
如何在程序运行中改变控件的背景颜色即触发窗口重绘可参考这篇文章:http://bbs.ednchina.com/BLOG_ARTICLE_1986921.HTM
关于修改对话框中一类控件如窗口上的所有静态文本框的颜色,可以用下述方法
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (nCtlColor == CTLCOLOR_STATIC) //判断参数nCtlColor为CTLCOLOR_STATIC
{
pDC-> SetTextColor(RGB(255,0,0)); //字体颜色
pDC-> SetBkColor(RGB(0, 0, 255)); //字体背景色 ,注意SetBkColor函数设的是字体的背景色,不是控件的背景色
}
return hbr;
}
如果要修改某个特定控件的颜色可以这样写:ID为 IDC_STATIC1
if (pWnd-> GetDlgCtrlID()==IDC_STATIC1) //GetDlgCtrlID()会遍历窗口中所有的控件,返回ID
{
pDC-> SetTextColor(RGB(255,0,0)); //设置字体颜色
pDC-> SetBkMode(TRANSPARENT); //设置字体背景为透明
return (HBRUSH)::GetStockObject(BLACK_BRUSH); // 设置背景色
}
else
return hbr;
更多例子可以参考文章:http://blog.csdn.net/proing/article/details/5832691?reload和http://blog.const.net.cn/a/11092.htm
如何设置控件背景颜色,为何用SetBkColor设置背景颜色没有作用?可以参考这篇文章:http://www.myexception.cn/vc-mfc/171506.html
都是前人的工作,我主要是借鉴学习,在此将收集的资料整理了一下,根据文中重点针对的问题进行了分类。
Visual Studio程序开发要多参考msdn文档,很多知识都可以从文档中学到。