在VC++项目中为MDI主框架窗口添加位图

Visual C++提供的应用程序框架虽然可以自动生成多文档(MDI)的应用程序,但是程序的界面比较单调,如果能够在主框架中添加上彩色位图,一定能够大大改观程序的界面效果。目前也有些编程资料涉及到如何在MDI应用程序的主框架中添加彩色位图,但具体实践过程中都有一些小问题,为此,本实例介绍了一种比较简单可行的方法,可以在程序中圆满地实现这种功能,程序运行后的界面效果:
一、实现方法

  在多文档界面下,应用程序会自动生成一个新的子窗口,而一个实际的应用系统往往是由用户操作后再生成新的窗口。为了去掉开始的子窗口,方便在主框架中添加彩色位图,可在应用程序文件分析命令行的语句

CcommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
cmdInfo.m_nShellCommand=CcommandLineInfo::FileNothing;

  这时候编译运行程序就会反响去掉子窗口只剩下主框架窗口了。因为在多文档界面中,系统生成两个菜单:一个是用户的菜单,另一个是系统主框架菜单。通常用户工作在用户菜单。为了保证菜单界面不变,可修改主框架菜单资源,使其与用户菜单保持一致。

  下面我们进入正题,如何在主框架中添加位图。首先要清楚对于一个MDI应用程序的主框架窗口来说,它包含一个特殊的子窗口,称为MDICLIENT窗口,应用程序的主框架类中有一个成员变量m_hWndMDIClient 指的就是MDICLIENT窗口。MDICLIENT窗口负责管理主框架窗口的客户区。直接对MDI客户窗口编程有一定的难度,原因是MDIFrameWnd的客户区完全被MDICLIENT窗口覆盖掉了。正因为上述原因,MDI主窗口类MDIFrameWnd的背景色和光标都不起作用。同时,微软的MFC并不支持将MDICLIENT窗口作为子类,MDICLIENT窗口只能使用标准的背景色和光标,所以对MDI客户窗口编程不能象对普通窗口那样简单地重载WM_PAINT的消息处理函数。

  如何解决上述问题呢?解决的方法是我们可以在主框架窗口中截获关于MDICLIENT窗口的重画消息,然后加入自己设计的代码。例如重载PreTranslateMessage(MSG* pMsg)函数,截获MDI客户窗口WM_PAINT消息,在这个函数中向主框架窗口发送WM_PAINT消息,在该消息的处理函数中实现彩色位图的显示。PreTranslateMessage()是消息在送给TranslateMessage()函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用,当你需要在MFC之前处理某些消息时,常常要在这里添加代码。

  需要读者注意的是,不仅要在WM_PAINT消息响应函数中显示图像,还要在主框架类CMainFrame::OnCreate()函数中处理显示函数的代码,否则程序运行后仅显示灰色的背景,只有在窗口改变大小,需要重画时才显示出彩色位图。为什么会这样呢?笔者分析可能是框架的后续处理将最初绘制的彩色位图覆盖掉了。

  显示位图的时候用到了位图类CBitmap,CBitmap类封装了WINDOWS的图形设备接口(GDI)中的位图,并提供了很多操作位图的操作。我们还会用到它的一个函数LoadImage(),这个函数可以读入icon、cursor或bitmap,如果函数调用成功则返回读入的对象的句柄。此函数的原型如下:

BOOL LoadBitmap( LPCTSTR lpszResourceName );
BOOL LoadBitmap( UINT nIDResource );

  通过上面函数的定义,我们应该有一个思路了,要想加载位图资源可以有两种方式,一种是将位图导入到我们的资源文件中,一种直接从文件加载它。例如加载位图资源的方法如下:

//从资源文件加载位图
CBitmap m_bitmap; //建立一个位图对象;
m_bitmap.DeleteObject();
//调用CGdiObject的DeleteObject函数将以前的BITMAP对象删除。
m_bitmap.LoadBitmap(nBitmapID);//载入指定ID的图象资源nBitmapID是资源的ID;

  位图对象建立了,下面要作的是显示它,这便会用到设备环境。显示位图的步骤如下所示(注意两个DC的定义):

  1. 建立一个设备DC1,用来显示位图,它与某个要显示图像的窗口相关联;

  2. 建立一个内存DC2,它要与设备DC1相兼容;

  3. 建立一个位图对象,并载入位图;

  4. 选择位图对象选择到内存DC2中,最后通过StretchBlt()函数将内存DC的位图显示到设备DC上;

StretchBlt()函数的原型和参数说明如下:
BOOL StretchBlt( HDC hdcDest, //目标设备句柄;
int nXOriginDest, //目标矩形左上角的X坐标;
int nYOriginDest, //目标矩形左上角的Y坐标;
int nWidthDest, //目标矩形的宽度;
int nHeightDest, //目标矩形的高度;
HDC hdcSrc, //源设备句柄;
int nXOriginSrc, //源矩形左上角的X坐标;
int nYOriginSrc, //源矩形左上角的Y坐标;
int nWidthSrc, //源矩形的宽度;
int nHeightSrc, //源矩形的高度;
DWORD dwRop //光栅运算操作;);

  StretchBlt()函数的头文件为"wingdi.h"。其中,它的dwRop参数有15种操作,最常用的就是拷贝运算SRCCOPY了。当源设备和目标设备指定的矩形大小不相等时,函数会根据源矩形和目标矩形的大小比例对位图进行放大或缩小操作后,拷贝到目标设备中。这里再通俗的解释一下句柄,句柄是系统用来识别不同资源的一个唯一的识别码,通过它系统便可以快速正确的找到所要的资源。可以理解为指向资源对象的特殊指针。  

  二、编程步骤

  1、 启动Visual C++6.0,生成一个多文档的应用程序,将程序命名为"ShowBmp";

  2、 向程序添加256色彩色位图资源,命名为IDB_BITMAP1;

  3、 用Class Wizard向程序的主框架类CMainFrame添加函数CMainFrame::PreTranslateMessage(MSG* pMsg);

  4、 用ClassWizard向主框架类添加函数CMainFrame::OnPaint();

  5、 添加代码,编译运行程序。
  三、程序代码

/
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
  return -1;
 if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD |
WS_VISIBLE | CBRS_TOP| CBRS_GRIPPER |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
 {
  TRACE0("Failed to create toolbar/n");
  return -1; // fail to create
 }
 if (!m_wndStatusBar.Create(this) ||!m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))
 {
  TRACE0("Failed to create status bar/n");
  return -1; // fail to create
 }
 // TODO: Delete these three lines if you don't want the toolbar to
 // be dockable
 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
 EnableDocking(CBRS_ALIGN_ANY);
 DockControlBar(&m_wndToolBar);
 CDC dc, memdc;
 dc.m_hDC=::GetDC(this->m_hWndMDIClient);
 CRect rect;
 CBitmap bitmap;
 BITMAP szbitmap;
 bitmap.LoadBitmap(IDB_BITMAP1);
 bitmap.GetObject(sizeof(BITMAP),&szbitmap);
 CSize size(szbitmap.bmWidth,szbitmap.bmHeight);
 memdc.CreateCompatibleDC(&dc);
 CBitmap *oldbitmap=memdc.SelectObject(&bitmap);
 GetClientRect(&rect);
 StretchBlt(dc.m_hDC,0,0,rect.Width(),rect.Height(),
 memdc.m_hDC,0,0,size.cx,size.cy,SRCCOPY);
 memdc.SelectObject(oldbitmap);
 memdc.DeleteDC();
 dc.DeleteDC();
 return 0;
}
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
 // TODO: Add your specialized code here and/or call the base class
 if(pMsg->hwnd==m_hWndMDIClient && pMsg->message==WM_PAINT)
  PostMessage(WM_PAINT);
 return CMDIFrameWnd::PreTranslateMessage(pMsg);
}

void CMainFrame::OnPaint()
{
 CDC dc, memdc;
 dc.m_hDC=::GetDC(this->m_hWndMDIClient);
 CRect rect;
 CBitmap bitmap;
 BITMAP szbitmap;
 bitmap.LoadBitmap(IDB_BITMAP1);
 bitmap.GetObject(sizeof(BITMAP),&szbitmap);
 CSize size(szbitmap.bmWidth,szbitmap.bmHeight);
 memdc.CreateCompatibleDC(&dc);
 CBitmap *oldbitmap=memdc.SelectObject(&bitmap);
 GetClientRect(&rect);
 StretchBlt(dc.m_hDC,0,0,rect.Width(),rect.Height(),
 memdc.m_hDC,0,0,size.cx,size.cy,SRCCOPY);
 memdc.SelectObject(oldbitmap);
 memdc.DeleteDC();
 dc.DeleteDC();
 CMDIFrameWnd::OnPaint();
}

  四、小结

  本实例通过在MDI应用程序的主框架中显示彩色位图作为背景,讲述了图像资源显示的方法,读者朋友可以以此展开,将彩色位图显示到不同的控件上,如按钮、对话框等,同时灵活运用各种显示方式,
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Visual C++6.0使用GDI+的一般方法 1. 载解压GDI+开发包; 2. 正确设置include & lib 目录; 3. stdafx.h 添加: #ifndef ULONG_PTR #define ULONG_PTR unsigned long* #endif #include 4. 程序中添加GDI+的包含文件gdiplus.h以及附加的类库gdiplus.lib。 通常gdiplus.h包含文件添加在应用程序的stdafx.h文件中,而gdiplus.lib可用两种进行添加: 第一种是直接在stdafx.h文件中添加下列语句: #pragma comment( lib, "gdiplus.lib" ) 另一种方法是: 在VC.net中添加库文件在:项目菜单->属性->链接器->输入 举个例子: (1)在应用程序项目的应用类中,添加一个成员变量,如下列代码: ULONG_PTR m_gdiplusToken; 其中,ULONG_PTR是一个DWORD数据类型,该成员变量用来保存GDI+被初始化后在应用程序中的GDI+标识,以便能在应用程序退出后,引用该标识来调用Gdiplus:: GdiplusShutdown来关闭GDI+。 (2)在应用类中添加ExitInstance的重载,并添加下列代码用来关闭GDI+: int CGDITestApp::ExitInstance() { Gdiplus::GdiplusShutdown(m_gdiplusToken); return CWinApp::ExitInstance(); } (3)在应用类的InitInstance函数中添加GDI+的初始化代码: 注意:下面这些GDI+的初始化代码必须放在m_pMainWnd->UpdateWindow();之前。 CWinApp::InitInstance(); Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); (4)在需要绘图的窗口或视图类中添加GDI+的绘制代码。 下面分别就单文档和基于对话框应用程序为例,说明使用GDI+的一般过程和方法。 1. 在单文档应用程序中使用GDI+ 在上面的过程中,我们就是以一个单文档应用程序Ex_GDIPlus作为示例的。下面列出第4步所涉及的代码: void CGDITestView::OnDraw(CDC* pDC) { CGDITestDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here usingnamespace Gdiplus; Graphics graphics(pDC->m_hDC); Pen newPen(Color(255,0,0),3); HatchBrush newBrush(HatchStyleCross,Color(255,0,255,0),Color(255,0,0,255));//创建一个填充画刷,前景色为绿色,背景色为蓝色 graphics.DrawRectangle(&newPen,50,50,100,60);// 在(50,50)处绘制一个长为100,高为60的矩形 graphics.FillRectangle(&newBrush,50,50,100,60); // 在(50,50)处填充一个长为100,高为60的矩形区域 } 编译并运行,结果如图:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值