导航

给对话框加背景色

Posted on 2009-05-30 21:21  无意乂  阅读(3408)  评论(1编辑  收藏  举报

1.给对话框加背景色

当Windows系统需要重画某个窗口客户区的背景的时候,就会向该窗口发送WM_ERASEBKGND 消息,窗口的处理过程响应这个消息重新画窗口的背景。改变对话框的背景颜色的原理很简单,就是响应这个消息,用自定义的颜色填充对话框的客户区背景,代替对话框窗口默认的背景填充动作。

因此给对话框加背景色只需要响应WM_ERASEBKGND就可以了.如下:

BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)
{
    CRect clientRect;
    GetClientRect(
&clientRect);
    pDC
->FillRect(&clientRect, &m_backgroundBrush);
    
return TRUE;
    
//return CDialog::OnEraseBkgnd(pDC);
}


m_backgroundBrush是个CBrush对象,在InitDialog中就初始化好了的.

m_backgroundBrush.CreateSolidBrush(RGB(200200255));


但是仅给对话框加了背景还不行.控件的背景还是灰色.像有些桌面图标下面的字没开阴影的那种效果.很丑很丑..
因此还要给控件加上背景才行

 

2.给控件加背景色

这里要该响应WM_CTLCOLOR消息了.同时涉及到一个"消息反射"的概念.

WM_CTLCOLOR是Windows的控件向其父窗口发送最频繁的通知消息之一,例如,许多控件发送WM_CTLCOLOR消息给父窗口,让父窗口提供画刷来画自己的背景.MFC的窗口类对这个通知消息特殊对待.如果父窗口没有处理这个通知消息,MFC的窗口类就根据WM_CTLCOLOR通知消息的来源将这个WM_CTLCOLOR消息发送回控件,让控件自己处理,这就是所谓的"消息反射".不仅是WM_CTLCOLOR,MFC对很多通知消息都做了反射.

因此我们只要在收到控件的WM_CTLCOLOR消息时准备好相应的画刷返回了就可以了. 

HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr 
= CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    pDC
->SetTextColor(RGB(0,0,0));    //设置字体前景色为黑色
    pDC->SetBkMode(TRANSPARENT);    //设置字体背景色为透明
    return (HBRUSH)m_backgroundBrush;       //因为CBrush类实现了HBRUSH类型转换操作符
    
//return hbr;
}

 hbr是默认的画刷.灰色或者白色背景的那种,所以我们要返回自己定义好背景色的画刷.

如果要对不同类型的控件设置不同的颜色可以根据nCtlColor的值来确定.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

 也可以用pWnd->GetDlgCtrlID()取得控件ID号来对单个控件进行设置.

 

对于多行的edit.如果用了pDC->SetBkColor.而设的颜色又与返回的画刷颜色不一致的话就会出现下面的情况..
有字的地方是一种背景色.没字的那几行又是一种颜色.


因此可以再多准备一个CBrush对象.专门用来保存edit的背景色.用来在OnCtlColor中返回给edit

 

但是这样又会出现新问题,很多时候edit没有刷新,字符重叠在一起(比如显示超过一屏的内容),按下退格键时删掉的字符也没有消失.很麻烦啊..
解决方法还是只有由CEit派生出一个类.重载里面的OnEraseBkgnd,OnGetDlgCode,OnMouseMove等消息函数.详细的去下面两个帖子看吧:
关于CEdit控件的透明 如何在EDITBOX控件中使用背景位图

如果要派生CEdit的话也好可以好好利用下WM_CTLCOLOR的消息反射.
在子类中响应WM_CTLCOLOR消息.这样就可以不用在父窗口里面设置控件的颜色了.更利于封装吧

 

但是控件中的滚动条始终顽固地保持着它一贯的灰色.要解决的方法...不知道.

 

3.背景图片

大概就是好好改造那些个CBrush对象吧.我没试,就不写了

看到段话,先堆这吧..

使用位图作为对话框的背景也很简单,就是在OnEraseBkgnd中用位图填充客户区,只是在OnCtlColor中需要注意返回空画刷代替原来的画刷,返回空画刷是为了阻止控件绘制自己的背景,从而破坏位图背景的完整性,但是有时候返回空画刷会对其他控件产生不良影响.