MFC设置窗体背景图片(画刷)先载入一张图片,ID为IDB_BITMAP2TestDlg.h中:CBrush m_brBk;//在public中定义TestDlg.cpp中:在初始化函数OnInitDialog()中加入:BOOL CTestDlg::OnInitDialog(){CDialog::OnInitDialog();CBitmap bmp;bmp.LoadBitmap(IDB_BITMAP2);m_brBk.CreatePatternBrush(&bmp);bmp.DeleteObject();return TRUE; // return TRUE unless you set the focus to a control}再打开类向导,找到WM_CTLCOLOR消息,重载得对应函数OnCtlColor(),添加如下:HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor){HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);if (pWnd == this){return m_brBk;}return hbr;}按照上面的方法一路COPY下来运行,OK!并且由于图片是做为背景显示的,所以再添的按钮都能很好的显示出来,非常方便。
总结一下其中出现的变量和函数。
CBrush:类CBrush封装了Windows图形设备接口(GDI)中的画刷,画刷也就是采取什么方案填充图形的背景的工具。
OnInitDialog ( ):用于对对话框类的变量的初始化(注意:是在产生对话框之前就初始化),是WM_INITDIALOG消息产生的消息处理函数,覆盖该函数可改变对话框初始设置。
用法:virtual BOOL OnInitDialog();返回值指定对话框是否对它的一个控件设置输入焦点。
如果OnInitDialog返回非零值,Windows 将输入焦点设在对话框的第一个控件上,只有在对话框明确将输入焦点设在某控件上,应用返回0。
CBitmap:类CBitmap封装了Windows图形设备接口(GDI)中的位图,并且提供操纵位图的成员函数。
LoadBitmap ( ):CBitmap类的一个成员函数,从应用的可执行文件中加载一个命名的位图资源来初始化位图对象。
用法:BOOL LoadBitmap( LPCTSTR lpszRecourceName );BOOL LoadBitmap( UINT nIDResource );返回值调用成功时返回非零值,否则为0。
参数lpszResourceName指向一个包含了位图资源名字的字符串(该字符串以null结尾)。
NIDResource指定位图资源中资源的ID号。
本函数从应用的可执行文件中加载由lpszResourceName指定名字或者由nIDResource指定的ID号标志的位图资源。
加载的位图被附在Cbitmap对象上。
如果由lpszResourceName指定名字的对象不存在,或者没有足够的内存加载位图,函数将返回0。
可以调用函数CgdiObject::DeleteObject删除由LoadBitmap加载的位图,否则Cbitmap的析构函数将删除该位图对象。
CreatePatternBrush ( ):CBrush类的一个成员函数,用位图指定的模式初始化画刷。
用法:BOOL CreatePatternBrush( CBitmap* pBitmap );返回值调用成功时返回非零值,否则为0。
参数pBitmap指定一个位图。
本函数用位图指定的模式初始化画刷。
此画刷随后就可用于任何支持光栅操作的设备上下文。
由bBitmap指定的位图一般用以下的函数初始化:CBitmap:: CreateBitmap、CBitmap::CreateBitmapIndirect、CBitmap::LoadBitmap或Cbitmap::CreateCompatibleBitmap。
DeleteObject ( ):CgdiObject类的一个成员函数,从内存中删除附加给CGdiObject的Windows GDI对象,释放与此对象相关的系统存储空间。
GdiObject类为各种Windows图形设备接口(GDI)对象,如位图、区域、画刷、画笔、调色板、字体等提供了一些基本类。
我们不会直接构造一个CGdiObject对象,而是使用某一个派生类如CPen或CBrush创建。
用法:BOOL DeleteObject( );如果GDI对象被成功删除,则返回非零值,否则为0。
通过释放附加的GDI对象占有的系统存储来删除它们。
与CGdiObject对象有关的存储不受此调用的影响。
如果CGdiObject对象正被选入设备上下文中,则应用不可对此对象调用DeleteObject。
当一个模式画刷被删除时,与之相关联的位图不被删除。
位图必须被独立删除。
HBRUSH:数据类型,用于定义画刷句柄。
在Windows环境中,句柄是用来标识项目的,这些项目包括:module, task,instance, file ,block of memory, menu, control, font, resource, icon, cursor, string, GDI object等,包括bitmap, brush, metafile, palette, pen, region以及设备描述表device context。
实际上,句柄是一个标识符,用来表示对象或者项目,是一个32位的正整数。
应用程序几乎总是通过调用一个Windows函数来获得一个句柄,之后其他的Windows 函数就可以使用这个句柄, 以引用相应的对象。
WM_CTLCOLOR消息:WM_CTLCOLOR是一个由控制(Control)发送给它父窗口的通知消息(Notification message)。
利用向导映射该消息产生函数:HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);参数pDC是TestDlg的设备上下文,pWnd是TestDlg中发送该消息的control指针,nCtlColor是Control的类型编码。
WM_CTLCOLOR是系统在绘制控件的时候自动发送的,如果需要自定义,就截取这个消息并重载它的响应函数,用classWizard添加WM_CTLCOLOR 消息然后编辑其OnCtlColor函数。
这样Windows向应用程序发送消息WM_CTLCOLOR,应用程序处理WM_CTLCOLOR消息并返回一个用来绘画窗体背景的刷子句柄//放在OnPaint()里{//设置背景图片CRect rect;GetClientRect(&rect);CDC *pDC=GetDC();CDC memdc;memdc.CreateCompatibleDC(pDC);CBitmap bitmap;//从资源中载入位图bitmap.LoadBitmap(IDB_BITMAP1);memdc.SelectObject(bitmap);pDC->BitBlt(0,0,rect.Width(),rect.Height(),&memdc,0,0,SRCCOPY);}对于VC++文档、视结构中的视图,从用户的角度来看,只是可以改变大小、位置的普通窗口,同其他基于Windows应用程序的窗口是一样的;从程序员的角度来看,视图并不是普通的窗口,而是从MFC库中CView类派生的类对象。
像任何VC++对象一样,视图对象的行为由类的成员函数(数据成员)决定,包括派生类中应用程序定义的函数和从基类继承来的函数。
提出问题视图的背景一般来说是白色的,在缺省情况下,它和系统定义的颜色COLOR_WINDOW 是一致的。
设计者一般会希望自己的程序可以让用户轻松地改变窗口背景颜色,或是用漂亮的图片来充填背景。
澳门新濠天地官网 我们可以用Windows函数SetSysColors 来重新指定COLOR_WINDOW所对应的实际颜色,来达到改变视图背景颜色的目的。
但这样会同时改变其他应用程序的视图窗口背景,使得整个Windows系统的颜色设置产生混乱。
另外,我们可能会用以下方法来设置视图的背景颜色,即在CView的OnDraw函数中添写如下一段程序代码:void CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);CRect rectClient;CBrush brushBkColor;GetClientRect(rectClient);brushBkColor.CreateSolidBrush(RGB(255,0,0));pDC->DPtoLP(rectClient);pDC->FillRect(rectClient,&brushBkColor);…}这样可以达到改变当前应用程序的视图背景的目的,但同时也产生了一些不良影响,使得程序运行效果不尽如人意。
分析问题我们知道,在VC++的文档、视结构中,CView的OnDraw函数用于实现绝大部分图形绘制的工作。
如果用户改变窗口尺寸,或者显示隐藏的区域,OnDraw函数都将被调用来重画窗口。
并且,当程序文档中的数据发生改变时,一般必须通过调用视图的Invalidate(或InvalidateRect)成员函数来通知Windows所发生的改变,对Invalidate的调用也会触发对OnDraw函数的调用。
正因为OnDraw函数被频繁调用,所以在其执行时,每次都刷新填充一次视图客户区域,便会使屏幕不稳定,产生闪烁现象。
笔者通过对VC++应用程序框架结构和Windows消息映射系统的仔细研究,找到另外一种改变视图背景的方法,其执行效果比上述两种方法都好。
其实在程序调用OnDraw函数之前,会触发一个Windows消息:WM_ERASEBKGND,以擦除视图刷新区域。
在缺省情况下,Windows系统使用视图窗口注册时窗口类中的成员hbrBackground所描述的画刷来擦除屏幕,这一般会将屏幕刷新成COLOR_WINDOW所对应的颜色。
因此,在OnDraw函数中设置背景颜色的执行过程是这样的:先将屏幕刷新成COLOR_WINDOW所对应的颜色,接着又在OnDraw函数中填充其他颜色,这正是产生屏幕闪烁的根本原因。
解决问题通过上述分析,我们应将视图背景颜色填充移到Windows消息:WM_ERASEBKGND所对应的消息映射函数中,而不是在OnDraw函数中。