mfc修改窗口背景,mfc窗口背景色

  mfc修改窗口背景,mfc窗口背景色

  来自:http://blog . . net/Leo lee 82/article/details/6992626

  首先,加载ID为IDB_BITMAP2的图片

  在TestDlg.h中:

  CBrush m _ brBk//公开定义

  在TestDlg.cpp中:

  在初始化函数OnInitDialog()中,添加:

  【cpp】查看plaincopyprint?

  BOOLCTestDlg:OnInitDialog(){ CDialog:OnInitDialog();CBitmapbmpbmp。load bitmap(IDB _ bitmap 2);m_brBk。CreatePatternBrush(BMP);bmp。delete object();returnTRUE//returntruunellessyousetthefocustoacontrol }

  BOOL CTestDlg:OnInitDialog()

  CDialog:OnInitDialog();

  CBitmap bmp

  bmp。load bitmap(IDB _ bitmap 2);

  m_brBk。CreatePatternBrush(BMP);

  bmp。delete object();

  返回TRUE//除非将焦点设置到控件上,否则返回TRUE

  }

  再次打开类向导,找到WM_CTLCOLOR消息,以及重载的对应函数OnCtlColor()。

  添加以下内容:

  【cpp】查看plaincopyprint?

  HBRUSHCTestDlg:onctl color(CDC * pDC,CWnd*pWnd,UINTnCtlColor){ hbrushbr=CDialog:onctl color(pDC,pWnd,nCtlColor);if(pWnd==this){ returnm _ brBk;} returnhbr}

  HBRUSH CTestDlg:onctl color(CDC * pDC,CWnd* pWnd,UINT nCtlColor)

  HBRUSH HBR=CDialog:onctl color(pDC,pWnd,nCtlColor);

  如果(pWnd==this)

  返回m _ brBk

  返回hbr

  按照上面的方法一路抄下来跑,OK!而且因为图片是作为背景显示的,所以添加的按钮也能很好的显示出来,非常方便。

  总结其中出现的变量和函数。

  CBrush:类CBrush将画笔封装在Windows图形设备接口(GDI)中,画笔是一个用任意方案填充图形背景的工具。

  NitDialog():用于初始化Dialog类的变量(注意:是在对话框生成之前初始化的)。它是由WM_INITDIALOG消息生成的消息处理函数。覆盖此函数可以更改对话框的初始设置。

  用法:

  虚拟BOOL OnInitDialog();指定返回值对话框是否为它的一个控件设置输入焦点。如果OnInitDialog返回非零值,Windows将输入焦点设置在对话框的第一个控件上。只有当对话框在控件上显式设置输入焦点时,应用程序才返回0。

  cbit map:cbit map类将位图封装在Windows图形设备接口(GDI)中,并提供成员函数来操作位图。

  LoadBitmap ():CBitmap类的CBitmap成员函数,它从应用程序的可执行文件中加载一个已命名的位图资源,以初始化位图对象。

  用法:

  BOOL load bitmap(LPCTSTR lpszRecourceName);BOOL load bitmap(UINT NID resource);当调用成功时返回一个非零值,否则为0。参数lpszResourceName指向包含位图资源名称的字符串(该字符串以null结尾)。指定位图资源中资源的ID号。这个函数从应用程序的可执行文件中加载由lpszResourceName指定的名称或由nIDResource标记的ID号的位图资源。加载的位图被附加到Cbitmap对象。如果由lpszResourceName命名的对象不存在,或者没有足够的内存来加载位图,该函数将返回0。可以调用函数CgdiObject:DeleteObject删除LoadBitmap加载的位图,否则Cbitmap的析构函数会删除位图对象。

  CreatePatternBrush():C Brush类的成员函数,用位图指定的图案初始化画笔。

  用法:

  BOOL CreatePatternBrush(cbit map * pbit map);当调用成功时返回一个非零值,否则为0。参数pBitmap指定位图。这个函数用位图指定的图案初始化画刷。然后,这个画笔可以在任何支持光栅操作的设备上下文中使用。bBitmap指定的位图一般用以下函数初始化:CBitmap: CreateBitmap、CBitmap:CreateBitmapIndirect、CBitmap:LoadBitmap或cbit map:create compatible bitmap。

  delete object():CGdiObject类的成员函数,从内存中删除附加在CGdiObject上的Windows GDI对象,释放与该对象相关的系统存储空间。GDI类为各种Windows图形设备接口(GDI)对象提供了一些基本类,如位图、区域、画笔、画笔、调色板、字体等。我们将使用派生类(如CPen或CBrush)来创建CGdiObject对象,而不是直接构造它。

  用法:

  BOOL delete object();如果GDI对象删除成功,则返回非零值,否则为0。通过释放被附加的GDI对象占用的系统存储空间来删除它们。与CGdiObject对象相关的存储不受此调用的影响。如果CGdiObject对象被选择到设备上下文中,应用程序就不能在这个对象上调用DeleteObject。删除图案画笔时,与其关联的位图不会被删除。位图必须单独删除。

  HBRUSH:数据类型,用于定义画笔句柄。在Windows环境中,句柄用于标识项目,包括:模块、任务、实例、文件、内存块、菜单、控件、字体、资源、图标、光标、字符串、gdiobject等。包括位图。画笔、图元文件、调色板、笔、区域和设备描述表设备上下文。实际上,句柄是一个标识符,用来表示一个对象或一个项目。它是一个32位正整数。应用程序几乎总是调用一个Windows函数来获得一个句柄,然后其他Windows函数可以使用这个句柄来引用相应的对象。

  WM_CTLCOLOR消息:WM_CTLCOLOR是控件发送给其父窗口的通知消息。使用向导映射消息生成功能:

  HBRUSH CAboutDlg:onctl color(CDC * pDC,CWnd* pWnd,UINT nCtlColor);

  PDC是TestDlg的设备上下文,pWnd是TestDlg中发送此消息的控制指针,nCtlColor是控制的类型代码。WM_CTLCOLOR由系统在绘制控件时自动发送。如果需要定制,拦截这个消息,重载它的响应函数。使用classWizard添加WM_CTLCOLOR消息,然后编辑其OnCtlColor函数。这样,Windows向应用程序发送消息WM_CTLCOLOR,应用程序处理WM_CTLCOLOR消息并返回绘制窗体背景的画笔句柄。

  【cpp】查看plaincopyprint?

  //放入OnPaint(){//设置背景图片CRectrectGetClientRect(rect);CDC * pDC=GetDC();CDCmemdcmemdc。CreateCompatibleDC(pDC);CBitmapbitmap//加载位图位图。从资源加载位图(IDB_BITMAP1 );memdc。SelectObject(位图);pDC- BitBlt(0,0,rect。Width(),rect。Height(),memdc,0,0,src copy);}

  //放在OnPaint()中

  {//设置背景图片

  CRect rect

  GetClientRect(rect);

  CDC * pDC=GetDC();

  CDC memdc

  memdc。CreateCompatibleDC(pDC);

  CBitmap位图;

  //从资源中加载位图

  位图。load bitmap(IDB _ bitmap 1);

  memdc。SelectObject(位图);

  pDC- BitBlt(0,0,rect。Width(),rect。Height(),memdc,0,0,src copy);

  对于可视化结构的v c++文档和视图,从用户的角度来看,它只是一个大小和位置可以改变的普通窗口,和其他基于Windows的应用程序一样。从程序员的角度来看,视图不是普通的窗口,而是从MFC库中的CView类派生出来的类对象。像任何v c++对象一样,视图对象的行为由类的成员函数(数据成员)决定,包括应用程序在派生类中定义的函数和从基类继承的函数。

  提出问题

  视图的背景通常是白色的。默认情况下,它与系统定义的颜色COLOR_WINDOW一致。设计者一般都希望他们的程序可以让用户方便地改变窗口的背景颜色,或者用漂亮的图片填充背景。我们可以使用窗口函数SetSysColors重新指定COLOR_WINDOW对应的实际颜色来改变视图的背景色。但是这样会同时改变其他应用的视图窗口背景,造成整个Windows系统颜色设置的混乱。另外,我们可以使用下面的方法来设置视图的背景颜色,即在CView的OnDraw函数中添加下面的程序代码:

  【cpp】查看plaincopyprint?

  void ctest view:OnDraw(CDC * pDC){ CTestDoc * pDoc=get document();ASSERT _ VALID(pDoc);CRectrectClientCBrushbrushBkColorGetClientRect(rect client);brushBkColor。CreateSolidBrush(RGB(255,0,0));pDC-DPT olp(rect client);pDC- FillRect(rectClient,& brushBkColor);…}

  void CTestView:OnDraw(CDC* pDC)

  CTestDoc * pDoc=get document();

  ASSERT _ VALID(pDoc);

  CRect rectClient

  CBrush brushBkColor

  GetClientRect(rect client);

  brushBkColor。CreateSolidBrush(RGB(255,0,0));

  pDC-DPT olp(rect client);

  pDC- FillRect(rectClient,& brushBkColor);

  }

  这样可以达到改变当前应用的视图背景的目的,但同时也有一些不利的影响,使得程序的运行效果不尽如人意。

  分析问题

  我们知道,在VC++的文档和可视化结构中,使用CView的OnDraw函数来实现大部分的图形绘制工作。如果用户改变窗口大小或显示隐藏区域,将调用OnDraw函数来重画窗口。而且当程序文档中的数据发生变化时,一般需要通过调用视图的Invalidate(或invalidator)成员函数来通知Windows发生了变化,对Invalidate的调用也会触发对OnDraw函数的调用。由于OnDraw函数被频繁调用,在执行时,视图的客户区每次都被刷新和填充,会导致屏幕不稳定和闪烁。

  通过对v c++应用程序序列框架和Windows消息映射系统的仔细研究,作者找到了另一种改变视图背景的方法,其执行效果优于以上两种方法。其实在程序调用OnDraw函数之前,会触发一个Windows消息:WM_ERASEBKGND擦除视图刷新区域。Windows系统默认使用注册视图窗口时window类的成员hbrBackground描述的画笔来擦除屏幕,一般会将屏幕刷新为COLOR_WINDOW对应的颜色。所以在OnDraw函数中设置背景色的执行过程是这样的:首先将屏幕刷新为COLOR_WINDOW对应的颜色,然后在OnDraw函数中填充其他颜色,这是导致屏幕闪烁的根本原因。

  解决问题

  通过上面的分析,我们应该把视图的背景色填充移到Windows消息对应的消息映射函数:WM_ERASEBKGND,而不是OnDraw函数。我们可以通过以下步骤来实现这个过程:在document类中添加一个成员变量m_viewBkColor来保存当前的背景色,并添加两个成员函数GetViewBkColor和SetViewBkColor来读写它。这样做的好处是m_viewBkColor成员可以序列化并与文档链接。当打开一个文档时,其背景将与程序上次操作该文档时的背景保持一致。将消息映射函数OnEraseBkgnd添加到view类中视图的Windows消息WM_ERASEBKGND中。代码如下:

  【cpp】查看plaincopyprint?

  BOOLCTestView:OnEraseBkgnd(CDC * pDC){ CRectrect;CBrushbrush刷。CreateSolidBrush(get document()-GetViewBkColor());pDC-GetClipBox(rect);pDC- FillRect(矩形,&刷子);returntrue}

  BOOL ctest view:OnEraseBkgnd(CDC * pDC)

  CRect rect

  CBrush画笔;

  刷。CreateSolidBrush(get document()-GetViewBkColor());

  pDC-GetClipBox(rect);

  pDC- FillRect(矩形,&刷子);

  返回true

  }

  在这个函数中,不需要将设备坐标转换为客户区域矩形的逻辑坐标,并且当Windows调用这个函数时,它会自动计算裁剪区域,这样就可以将需要刷新的屏幕区域最小化。这样我们在程序中通过设计以下菜单功能就可以很容易的改变视图背景的颜色,运行效果还是比较满意的。

  【cpp】查看plaincopyprint?

  void ctest view:OnChangeViewBkcolor(){ CColorDialogcdlg;如果(cdlg。DoModal()==IDOK){ get document()-SetViewBkColor(cdlg。GetColor());invalidatory(NULL);}}

mfc修改窗口背景,mfc窗口背景色