您的位置:首页 > 其它

MFC修改对话框及控件背景颜色 - 很轻松!

2016-07-20 11:01 525 查看
1、修改静态文本框、编辑框、按钮等子控件的显示效果

MFC中对主窗口和子控件重绘之前都会调用OnCtlColor函数来进行一些基本的属性设置,如设置子控件的背景模式(是否透明等)、文本颜色、字体等属性。

因此要实现对子控件的背景颜色、文本颜色或字体背景等属性的修改就可以重载WM_CTLCOLOR消息的响应函数.此函数的

原型:
afx_msg HBRUSH OnCtlColor(CDC *pDC,CWnd *pWnd,UINT nCtlColor); 
参数:

pDC当前需要重绘控件的DC指针。

pWnd当前需要重绘控件的窗口指针。

nCtlColor用于指定控件的类型,可以是:
CTLCOLOR_BTN 
按钮控件
CTLCOLOR_DLG 
对话框
CTLCOLOR_EDIT 
编辑框
CTLCOLOR_LISTBOX 
列表控件
CTLCOLOR_MSGBOX 
消息控件
CTLCOLOR_SCROLLBAR 
滚动条控件
CTLCOLOR_STATIC 
静态控件

返回值:返回一个画刷,也就是使用返回的这个画刷来对子控件的背景(或主对话框)进行修改。

注意:此函数并非只能修改子控件的属性,当主对话框本身进行重绘时也会调用此函数,并使用此函数返回的画刷来重绘对话框的背景!

假设你已有了名为My的对话框工程.你有了两个STATIC的控件IDC_STATIC1和IDC_STATIC2、两个按钮控件IDC_BUTTON1和IDC_BUTTON2。此函数简单实用见实例1:

HBRUSH CMyDlg::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)//如果当前控件属于静态文本 {  pDC-> SetTextColor(RGB(255,0,0)); //字体颜色 //pDC->SetBkMode(TRANSPARENT); //设置字体背景为透明 pDC-> SetBkColor(RGB(0, 0, 255));  //字体背景色 }  else if (nCtlColor==CTLCOLOR_BTN) //如果当前控件属于按钮 {  pDC-> SetTextColor(RGB(255,0,0)); //字体颜色 //pDC->SetBkMode(TRANSPARENT); //设置字体背景为透明 pDC-> SetBkColor(RGB(0, 0, 255));  //字体背景色 }  // TODO: Return a different brush if the default is not desired return hbr; }

这样IDC_STATIC1、IDC_STATIC2、IDC_BUTTON1和IDC_BUTTON2都被设置了红色字体、字体背景为l蓝色,显示效果如下所示:



这是IDC_STATIC1的显示效果。
注意:必须搞清楚字体背景空间背景区别。如图中蓝色部分是字体的背景,而蓝色+白色才是次STATIC控件的背景区域。而
SetBkColor和SetBkMode是针对字体背景做修改的,所以SetBkColor和SetBkMode是不能同时使用的,原因很简单:既然已经设置为字体背景透明,又怎么能再设置字体背景颜色呢?
一下是SetBkMode函数的使用案例,实例2:

HBRUSH CMyDlg::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)//如果当前控件属于静态文本
{
pDC-> SetTextColor(RGB(255,0,0)); //字体颜色
pDC->SetBkMode(TRANSPARENT); //设置字体背景为透明
//pDC-> SetBkColor(RGB(0, 0, 255)); //字体背景色
}
else if (nCtlColor==CTLCOLOR_BTN) //如果当前控件属于按钮
{
pDC-> SetTextColor(RGB(255,0,0)); //字体颜色
pDC->SetBkMode(TRANSPARENT); //设置字体背景为透明
//pDC-> SetBkColor(RGB(0, 0, 255)); //字体背景色
}
// TODO: Return a different brush if the default is not desired
return hbr;
}

其效果为:



可见只是将字体的背景变成了透明。要想实现相对对话框的背景透明就需要再OnCtlColor返回时返回一个透明画刷(也即空画刷)
,见实例3

HBRUSH CMyDlg::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)//如果当前控件属于静态文本
{
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
else if (nCtlColor==CTLCOLOR_BTN) //如果当前控件属于按钮
{
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
// TODO: Return a different brush if the default is not desired
return hbr;
}

效果为:



这个应该就是我们想要的效果了!
以上只是针对静态文本框的,看起来貌似很容易实现预期效果,但是对于按钮,其字体和字体背景的修改和静态文本框如出一辙,但在按照以上方式修改按钮背景时却碰到了麻烦。例如,我们打算使用以下方式修改所有按钮(IDC_BUTTON1和IDC_BUTTON2)的背景颜色(注意不是字体的背景),实例4:

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

// TODO: Change any attributes of the DC here
else if (nCtlColor==CTLCOLOR_BTN) //如果当前控件属于按钮
{
CBrush m_bkBrush; //准备一把主窗口背景刷子 m_bkBrush.CreateSolidBrush(RGB(0xff,0x00,0x00)); //创建一把黄色的背景刷子
return m_bkBrush; //返回刚才创建的背景刷子
}
// TODO: Return a different brush if the default is not desired
return hbr;
}
这样不能实现修改按钮背景的效果。因为,我们定义的是局部的m_bkBrush,这样在函数OnCtlColor返回时m_bkBrush就会被销毁释放掉,所以我们需要定义全局的m_bkBrush或将m_bkBrush定义成CMyDlg的成员变量。此外必须设置按钮的OwnerDraw属性为TRUE!不然按钮的背景不会被修改。
此处我们将m_bkBrush定义成CMyDlg的成员变量,并把按钮的OwnerDraw属性为TRUE,然后运行之后效果(IDC_BUTTON1):



这效果貌似让我们大失所望,原本按钮上的字都没了,而且还不能按下去了,不然会报错!!后来查了资料发现,这样修改按钮的背景时是会清空掉按钮上的文本。其实很多时候使用MFC是都会碰到类似的问题,明明思路都是对的,却就是不能实现,现在越来越发现MFC不好用了,不光很多小功能(就像我们这里简单的实现按钮背景修改)实现起来很复杂,而且实现的效果也和你一般,根本谈不上美观!有机会还是去玩Qt或Delphi。
为了解决这个问题找了很多资料都难以实现,在网上找的方法基本上都不管用,还说得跟真的一样,各种OnCtrlColor()和OnEraseBkground(),看了各种技术帝的方法看起来都很厉害,但是都不管用(真的很怀疑自己有没有做过,不过在中国本来就是技术帖子一大抄,只能忍了,参考而已嘛)。 
到最后发现,真正有用的办法自定义button类才能实现按钮颜色(自己实现了),即重载按钮类比较方便,重载后子类中SetBkColor就可以了。但是这个办法不免有些复杂,我不是勤快的人,这种方式适合只修改少量按钮背景的情况下使用,多以大量修改按钮背景的情况下就不推荐大家使用了,在这里也就不想往上写了(想了解此方法可参:考http://blog.csdn.net/liangzhonglin/article/details/3260349)。所以只能另辟蹊径了,介绍给大家一个很简单的方法
使用CMFCButton类便可以轻松实现这种功能。详细CMFCButton类使用方法请参考《BUTTON
- CMFCButton》。
------------------------------------------------------------------------------------------
以上那个都是针对某一类控件的整体设置,加入我只想设置IDC_STATIC1而不想改变IDC_STATIC2该怎么办呢?其实只要改变switch中的参数即可:

HBRUSH CDSCAMDEMODlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
//对特定的控件做修改
switch (pWnd->GetDlgCtrlID())
{
case IDC_STATIC1:
pDC->SetTextColor(RGB(0,0,0)); //设置字体颜色
pDC->SetBkColor(RGB(0,0,0)); //设置字体背景颜色
break;
case IDC_STATIC2://此段可忽略
break;
default:
break;
}}

2、修改对话框本身显示效果


例如修改对话框显示效果:

HBRUSH CDSCAMDEMODlg::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) //如果是CTLCOLOR_EDIT edit背景色能改变吗?
{
m_bkBrush.CreateSolidBrush(RGB(255,0,0)); //创建一把黄色的背景刷子
return m_bkBrush; //返回刚才创建的背景刷子
}
return hbr;}
这时,对话框背景为红色。
同理,m_bkBrush必须是全局变量或CDSCAMDEMODlg的成员变量!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: