MFC设置窗体背景图片(画刷) .

from:http://blog.csdn.net/leolee82/article/details/6992626

 

先载入一张图片,ID为IDB_BITMAP2

TestDlg.h中:
CBrush m_brBk;//在public中定义
TestDlg.cpp中:
在初始化函数OnInitDialog()中加入:

 

[cpp] view plaincopyprint?

  1. BOOL CTestDlg::OnInitDialog()  
  2. {  
  3. CDialog::OnInitDialog();  
  4. CBitmap bmp;  
  5. bmp.LoadBitmap(IDB_BITMAP2);  
  6. m_brBk.CreatePatternBrush(&bmp);  
  7. bmp.DeleteObject();  
  8. return TRUE; // return TRUE unless you set the focus to a control   
  9. }  

 

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(),
添加如下:

 

[cpp] view plaincopyprint?

  1. HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
  2. {  
  3. HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);  
  4.   
  5. if (pWnd == this)  
  6. {  
  7. return m_brBk;  
  8. }  
  9. return hbr;  
  10. }  

 

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消息并返回一个用来绘画窗体背景的刷子句柄

 

 

[cpp] view plaincopyprint?

  1. //放在OnPaint()里   
  2.   
  3. {//设置背景图片   
  4. CRect    rect;     
  5. GetClientRect(&rect);     
  6. CDC    *pDC=GetDC();     
  7. CDC    memdc;     
  8. memdc.CreateCompatibleDC(pDC);     
  9. CBitmap    bitmap;     
  10. //从资源中载入位图      
  11. bitmap.LoadBitmap(IDB_BITMAP1);     
  12. memdc.SelectObject(bitmap);     
  13. pDC->BitBlt(0,0,rect.Width(),rect.Height(),&memdc,0,0,SRCCOPY);  
  14. }  

 

//放在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函数中添写如下一段程序代码:

 

[cpp] view plaincopyprint?

  1. void CTestView::OnDraw(CDC* pDC)   
  2. {   
  3. CTestDoc* pDoc = GetDocument();   
  4. ASSERT_VALID(pDoc);   
  5. CRect rectClient;   
  6. CBrush brushBkColor;   
  7. GetClientRect(rectClient);   
  8. brushBkColor.CreateSolidBrush(RGB(255,0,0));   
  9. pDC->DPtoLP(rectClient);   
  10. pDC->FillRect(rectClient,&brushBkColor);   
  11. …   
  12. }   

 

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函数中。我们可以通过下列步骤实现这一过程:在文档类中增加一成员变量m_viewBkColor保存当前背景颜色,同时增加两个成员函数 GetViewBkColor和SetViewBkColor对其进行读写操作。这样做的好处是可以对m_viewBkColor成员进行序列化,将其和 文档联系在一起,打开某一文档时,其背景将和上一次程序操作该文档时的背景保持一致。在视图类中为视图的Windows消息WM_ERASEBKGND增 加消息映射函数OnEraseBkgnd,代码如下:

 

[cpp] view plaincopyprint?

  1. BOOL CTestView::OnEraseBkgnd(CDC* pDC)    
  2. {   
  3. CRect rect;   
  4. CBrush brush;   
  5. brush.CreateSolidBrush(GetDocument()->GetViewBkColor());   
  6. pDC->GetClipBox(rect);   
  7. pDC->FillRect(rect,&brush);   
  8. return true;   
  9. }   

 

BOOL CTestView::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
CBrush brush;
brush.CreateSolidBrush(GetDocument()->GetViewBkColor());
pDC->GetClipBox(rect);
pDC->FillRect(rect,&brush);
return true;
} 

在该函数中不需要对客户区域矩形进行设备坐标到逻辑坐标的转换,并且Windows在调用该函数时会自动进行裁剪区域的计算,使得需要刷新的屏幕面积达到最小。这样我们可以在程序中通过设计下列菜单函数轻松地改变视图背景的颜色,而且运行效果相当令人满意。

 

[cpp] view plaincopyprint?

  1. void CTestView::OnChangeViewBkcolor()    
  2. {   
  3. CColorDialog cdlg;   
  4. if(cdlg.DoModal()==IDOK)   
  5. {   
  6. GetDocument()->SetViewBkColor   
  7. (cdlg.GetColor());   
  8. InvalidateRect(NULL);   
  9. }   
  10. }   

 

时间: 2024-10-26 21:11:42

MFC设置窗体背景图片(画刷) .的相关文章

c#窗体背景图片-C#设置窗体背景图片,并让背景图片每隔五秒改变一次

问题描述 C#设置窗体背景图片,并让背景图片每隔五秒改变一次 怎么用C#设置Windows窗体的背景图片,并且让背景图片隔五秒变一次 解决方案 在你的窗体不属于任何方法的地方写: private int im = 0; 新建一个ImageList控件,添加4个图片. 新建一个定时器,设置interval=5000,enabled=true在tick里面写: this.BackgroundImage = ImageList1.Images[im++ % 4];

div布局-设置有背景图片的<div>块中怎么开发出一个白色的块?

问题描述 设置有背景图片的<div>块中怎么开发出一个白色的块? 我用一个图片添加为一个 的背景,然后想在这个块中再添加一个白的的块,但是这个快没法变为白色. 谢谢回答. 解决方案 贴代码,或者贴效果图. 解决方案二: 不知道你想要什么样的效果,在上面再加一个div就好了啊 解决方案三: 代码贴一下,这样不知道你要干什么 解决方案四: 浮上去一个白色的块就可以了啊 解决方案五: 我也是初学者 看看吧 不一定对 <!doctype html> <div style='backg

C++ 设置透明背景图片

  这篇文章主要介绍了C++ 设置透明背景图片的相关资料,需要的朋友可以参考下 背景: 有两个图片,一个是目标背景图片, 一个是带有自身背景色彩的彩色图片 先将这彩色图片绘制到目标背景图片中, 这一步通过BITBLT就可实现. 但实现后的效果是: 目标图片上,绘制上去的彩色图片带有其本身的背景. 问题就来了, 我们想将彩色图片本身的背景去掉,应该如何解决? 解决方法: 使用API函数:TransparentBlt 此函数将原DC中的图片绘制到目标DC中,并同时设置原图形在目标图形上的透明色. ?

css设置body背景图片随内容增加多少

 在CSS布局时,可能有时会遇到对body直接设置图片作为网页背景水平纵向平铺(从上到下居中平铺),此时整个网页无论内容是否占满一屏幕,css背景都会从上到下铺(纵向)满整个屏幕.但有时我们不需要这样的一个效果,需要内容占用多高,body背景就纵向从上到下铺满多少高度.很明显这样就达不到我们想要的效果. 解决方法:对html再设置个背景(无论图片还是纯色,推荐设置纯颜色的背景颜色) 接下来DIVCSS5通过实例为大家介绍此技巧,首先DIVCSS5分为两个案例,一个是直接对body设置背景图片从上

怎样设置word2013背景图片?

  1.首先打开word2013,这里小编先打开一个空白文档,先下面先给它设置背景图片,然后后面再上面写一段文字 2.在上面一行的菜单工具栏中点击"插入",打开插入功能选项,在插入功能中,我们可以插入各种能够插入的功能,如表格.图片.视频等. 3.因为我是要插入图片,所以这里点击"图片"按钮,点击后,会打开"插入图片"对话框,选择我们要作为背景的图片,然后点右下方的"插入"按钮,这样我们就把图片添加到文档中了,但是这个时候的图

c++-MFC对话框添加背景图片的问题

问题描述 MFC对话框添加背景图片的问题 按照大家的帮助,我在OnPaint函数中添加如下代码:void CsaoleiDlg::OnPaint(){ if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND reinterpret_cast<WPARAM>(dc.GetSafeHdc()) 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(

win10怎样设置桌面背景图片

本文图文介绍两种在windows10中设置桌面背景图片的方法 在桌面 右键点击鼠标,从菜单中选择"个性化" 在个性化设置中选择"背景" 然后在右边设置背景图片选项 - 最上面是实时的背景预览 - 默认的是"图片"类型的背景 - 可以从系统自带的图片中选择一张,也可以点击"浏览"选择自己电脑上的图片 也可以选择单纯的颜色作为桌面背景,可以在预览窗口实时查看效果 或者幻灯片放映图片,要从电脑中选择一组图片

您好!我现在想C#实现多个窗体背景图片同时更换该怎么写代码?

问题描述 您好!我现在想C#实现多个窗体背景图片同时更换该怎么写代码? public void pifu() { string tupian = comboBox1.Text; if (tupian == "1") { this.BackgroundImage = Image.FromFile(@"11.jpg"); return; } if (tupian == "2") { this.BackgroundImage = Image.FromF

Android设置桌面背景图片的实现方法_Android

1.设置桌面背景图片的方法 复制代码 代码如下: Resources res=getResources(); BitmapDrawable bmpDraw=(BitmapDrawable)res.getDrawable(R.drawable.icon); Bitmap bmp=bmpDraw.getBitmap(); try{ setWallpaper(bmp); }catch(IOException e) { e.printStackTrace(); } 2.在manifest中增加设置桌面的