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

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不好用了,不光很多小功能(就像我们这里简单的实现按钮背景修改)实现起来很复杂,而且实现的效果也和你一般,根本谈不上美观!有机会还是去玩QtDelphi
为了解决这个问题找了很多资料都难以实现,在网上找的方法基本上都不管用,还说得跟真的一样,各种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的成员变量!

你可能感兴趣的:(C++)