mfc 对话框设置背景,mfc颜色对话框
设置对话框背景颜色及背景图片可在OnCtlColor(),OnEraseBkgnd(),OnPaint()里设置,对话框初始化完毕,显示窗口时按顺序调用OnSize()OnEraseBkgnd()OnPaint()OnCtlColor()。
OnEraseBkgnd()中默认调用基类(CFrameWnd)的OnEraseBkgnd(),用窗口类中注册的刷绘制背景。因此,绘制窗口背景时最好重写OnEraseBkgnd(),但后面不能调用基类的OnEraseBkgnd()。
同时,MSDN关WM_ERASEBKGND消息的说明中有写道,DefWindowProc使用窗口类注册的背景刷绘制背景,如果背景刷是空,则需处理处理WM_ERASEBKGND消息。言外之意,处理WM_ERASEBKGND消息但不传给执行内定的消息处理就可以自己绘制背景,系统又不会重复绘制一遍。
当这个成员(背景画刷)为空,则每当应用程序被请求在其客户区绘制时,它必须绘制自己的背景。为了确定是否必须绘制背景,应用程序可以处理WM_ERASEBKGND消息,或者测试由开始绘画函数填充的绘图结构结构的转移酶成员。
方法如下:
【cpp】查看plaincopyprint?
BOOLCMainWindow:OnEraseBkgnd(CDC * pDC){//TODO:在此添加消息处理程序代码和/或调用默认值CRectrcGetClientRect(RC);pDC- FillSolidRect( rc,RGB(0,0,255));//returnCFrameWnd:OnEraseBkgnd(pDC);return true } BOOL c main window:OnEraseBkgnd(CDC * pDC)
//TODO:在此添加消息处理程序代码和/或调用默认值
获取控件矩形区域
GetClientRect(RC);
pDC- FillSolidRect( rc,RGB(0,0,255));
//返回CFrameWnd:OnEraseBkgnd(pDC);
返回真实的
}
当然,也可以重写OnEraseBkgnd()直接返回没错,然后在在线绘画()中改变背景。
更直接的方法是修改窗口类,实现更改背景颜色
【cpp】查看plaincopyprint?
BOOLCMainWindow:pre create window(create struct cs){//TODO:在此添加专用代码和/或调用基类if(CFrameWnd:pre create window(cs)){//改变窗口类WNDCLASSwndclass * GetClassInfo(AfxGetInstanceHandle()、cs.lpszClass、wndclass);//wnd类。HBR背景=(HBRUSH)(COLOR _ 3d face 1);//wnd类。HBR背景=(HBRUSH)GetStockObject(BLACK _ BRUSH);wnd类。hbrbackground=CreateSolidBrush(RGB(0,100,100));wnd类。HBR背景=m _ bk刷;//m_BKBrush不能为函数局部变量wnd类。HBR背景=*(new cbrush(RGB(25,25,0)));//最方便的方法//wnd类。hcursor=AfxGetApp()-load cursor(IDC _ cursor 1);wnd类。lpsz class name=_ T( new view class name );VERIFY(AfxRegisterClass(wnd类));cs。lpsz BOOL c main window:pre create window(创建结构cs)
//TODO:在此添加专用代码和/或调用基类
if(CFrameWnd:预创建窗口(cs))
//改变窗口类
WNDCLASS wndclass
* GetClassInfo(AfxGetInstanceHandle()、cs.lpszClass、wnd class);
//wnd类。HBR背景=(HBRUSH)(COLOR _ 3d face 1);
//wnd类。HBR背景=(HBRUSH)GetStockObject(BLACK _ BRUSH);
wnd类。hbrbackground=CreateSolidBrush(RGB(0,100,100));
wnd类。HBR背景=m _ bk刷;//m_BKBrush不能为函数局部变量
wnd类。HBR背景=*(新CB rush(RGB(25,25,0)));//最方便的方法
//wnd类。hcursor=AfxGetApp()-load cursor(IDC _ cursor 1);
wnd类。lpsz class name=_ T( new view class name );
VERIFY(AfxRegisterClass(wnd类));
cs.lpsz
若改变对话框大小,比如全屏显示显示窗口(SW _ show最大化);更新窗口();
其中橱窗会调用OnSize()- OnEraseBkgnd(),
更新窗口();调用OnPaint()- OnCtlColor(),
若对话框中没有设置消息响应OnEraseBkgnd(),则系统默认消息响应OnEraseBkgnd()会调用OnCtlColor()设置对话框背景(即替代OnEraseBkgnd())
对话框的背景设置可在OnCtlColor()中进行,因为OnCtlColor()一般会被多次调用,所以要想设置的CFont,CBrush等应在OnInitDialog中初始化,若要在OnCtlColor()中设置,在设置前先调用派遣就可以了,如下示例
【cpp】查看plaincopyprint?
HB rush CDB 3d LG:onctl color(CDC * PDC,cwnd * pwnd,uintnctlcolor){ if(pwnd-getdlgctrlid()==IDC _ static 5){ m _ font . createpointfont(300,?);pDC-select object(m _ font);m_font。detach();pDC- SetBkMode(透明);return(HBRUSH):GetStockObject(NULL _ BRUSH);} } HBRUSH CDB 3 DLG:onctl color(CDC * pDC,CWnd* pWnd,UINT nCtlColor)
if(pWnd-GetDlgCtrlID()==IDC _ static 5)
M_font。CreatePointFont(300,);
pDC-select object(m _ font);
m_font。detach();
pDC- SetBkMode(透明);
return(HBRUSH):GetStockObject(NULL _ BRUSH);
}
但是,如果背景图片是在OnCtlColor()中设置的,则图片不会随对话框的大小成比例缩放。
所以可以调用StretchBlt()函数来设置它,如下例所示:
【cpp】查看plaincopyprint?
void CDB 3 DLG:OnPaint(){ cclientdcdc(this);CDCcomdccomdc。CreateCompatibleDC(CDC);CBitmapbitmap位图。load bitmap(IDB _ bitmap 2);comdc。SelectObject(位图);CRectrectGetClientRect(rect);BITMAPbit位图。GetBitmap(位);疾病控制中心。StretchBlt(0,0,rect。Width(),rect。Height(),comdc,0,0,bit.bmWidth,bit.bmHeight,src copy);}//全屏显示对话框背景图片(仅限bmp格式)void CDb3Dlg:OnPaint()
CClientDC cdc(这个);CDC comdc
comdc。CreateCompatibleDC(CDC);
CBitmap位图;
位图。load bitmap(IDB _ bitmap 2);
comdc。SelectObject(位图);
CRect rect
GetClientRect(rect);
位图位;
位图。GetBitmap(位);
疾病控制中心。StretchBlt(0,0,rect。Width(),rect。Height(),comdc,0,0,bit.bmWidth,bit.bmHeight,src copy);
}//全屏显示对话框的背景图片(仅bmp格式)
对于窗口程序,一般有一个特点:窗口的大部分区域保持不变,只有没有区分的区域需要重画。如果整个窗口完全刷新,就会做很多不必要的工作。因此,MFC采用了一套基于无效区域的处理机制。在分析无效区域的处理之前,我们要明白一个现实,就是现在的机器还不够好。如果是,我们应该简单地不断重画整个窗口。其实就算再牛逼也不行。对于单线程程序,程序无法通过不断刷新窗口的while循环来响应其他消息(除非使用多线程)。似乎不可避免地要使用无效区域的处理机制。
VC程序是基于消息机制的。你做的任何操作,比如点击鼠标,拖动窗口,首先进入系统的消息队列。这里的系统消息队列包括来自多个程序的消息,然后系统将消息发送给相应的程序。既然是队列,就有先入先出的问题,屏幕上无效区域更新消息的频率会特别高。比如左上角的更新消息还没处理完,右下角的更新消息已经来了。为了避免多次处理WM_PAINT消息,系统会将这些窗口更新消息合并成一条消息,只将无效区域改为包含这两次更新无效区域的矩形区域。这样就减少了WM_PAINT消息的处理次数,提高了效率。
那么,如何更新OnPaint消息处理函数中的无效区域呢?首先,应该理解MFC中所有的绘制操作都是基于设备上下文(DC)的。具体可以参考任意一本VC教材。DC包含绘图设备的各种信息。对于屏幕绘图,实际上有一块内存(显存)专门用来存储屏幕上要显示的信息,显示器以85HZ的频率刷新它在屏幕上的内容(我之前的显示器)。关键点来了。显示器的刷新是将显存中的内容完全更新到显示器上,不存在无效区域处理的问题。那么,无效区域的处理必须发生在DC的绘图处理中。事实上,当程序调用OnPaint消息时,它首先将无效区域传输给DC。DC在绘图的时候,只更新无效区域的信息,不关心其他地方,提高了效率。
现在,你明白OnPaint在处理什么了吗?在这里,我也想说说Invalidate和UpdateWindow的区别。Invalidate在消息队列中添加一条WM_PAINT消息,其无效区域为整个客户区域。UpdateWindow直接发送一个WM_PAINT消息,其无效区是消息队列中仅有一个WM_PAINT消息(最多)的无效区。效果很明显。调用Invalidate后,屏幕不一定马上更新,因为WM_PAINT消息不一定在队列头,调用UpdateWindow会让WM_PAINT消息立即执行,绕过消息队列。如果希望在调用invalid后立即更新屏幕,请添加语句UpdateWindow()。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。