问题描述:

如上图所示,这是用MFC创建的多文档程序,可以看到主框架的背景区是灰色的,如果我要在这块区域贴一张图片,应该怎么办呢?最容易想到的是在CMainFrame的OnPaint中对背景进行更改,代码如下:
(为了简便,这里改为设置窗口背景色,其实这和贴图的原理差不多)
void CMainFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
RECT rc;
GetClientRect(&rc);
dc.FillRect(&rc,&CBrush(RGB(0,255,0)));
}
但运行之后你会发现并没有达到期望的效果。
下面我们来分析为什么会这样。


多文档窗口之主框架窗口的创建过程:
1.
在CMyTestApp::InitInstance中调用了
CMainFrame* pMainFrame = new CMainFrame;
pMainFrame->LoadFrame(IDR_MAINFRAME)

2.
在CMDIFrameWnd::LoadFrame中调用了
CFrameWnd::LoadFrame(nIDResource, dwDefaultStyle,pParentWnd, pContext)

在CFrameWnd::LoadFrame中含有
Create( lpszClass, strTitle, dwDefaultStyle, rectDefault,
pParentWnd, ATL_MAKEINTRESOURCE(nIDResource), 0L, pContext)

3.
CFrameWnd::Create中调用了
CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext)
该函数的rect、pParentWnd、pContext等参数是没有值的,这会调用CWnd的CreateEx方法,创建的窗口句柄存在m_hWnd成员变量中
之后便进入到CFrameWnd::OnCreate,然后再返回到本函数中
该函数执行完后返回到第2步

4.
CMainFrame::OnCreate
这是个消息响应函数,响应的是WM_CREATE消息,这里面调用了
CMDIFrameWnd::OnCreate(lpCreateStruct)

5.
CFrameWnd::OnCreate调用了
OnCreateHelper(lpcs, pContext)
lpcs中包含客户区、类名、标题、菜单等数据

6.
CFrameWnd::OnCreateHelper调用了
CWnd::OnCreate(lpcs)
然后又调用了
OnCreateClient(lpcs, pContext)

7.
CMDIFrameWnd::OnCreateClient中
CMenu* pMenu=GetMenu();
CreateClient(lpcs, pMenu)

CMDIFrameWnd中含有m_hWnd和m_hWndMDIClient成员变量,前者是在第3步时创建的CWnd窗口

8.
CMDIFrameWnd::CreateClient中的部分代码
ASSERT(m_hWnd != NULL);
ASSERT(m_hWndMDIClient == NULL);
m_hWndMDIClient = ::AfxCtxCreateWindowEx(dwExStyle, _T(“mdiclient”), NULL,
dwStyle, 0, 0, 0, 0, m_hWnd, (HMENU)AFX_IDW_PANE_FIRST,
AfxGetInstanceHandle(), (LPVOID)&ccs)

9.返回到第3步


在上面的分析过程中,通过第8步,可以看到,在主窗口框架中又建立了一个子窗口,该窗口的类型为”mdiclient”,该窗口的句柄为m_hWndMDIClient。也就是说,程序在创建完主框架窗口后,又在该窗口内部创建了一个客户区窗口,该客户区窗口就是我们看到的图中灰色区域的部分,其实也是我们要改变背景的部分,如果没有这个客户区窗口,那我们前面改变主框架窗口背景的代码是有效果的,但当该窗口创建后(该窗口的背景色为灰色),就又把之前改变了背景色的区域给挡住了。

通过上面的分析,我们知道了,只要改变m_hWndMDIClient窗口的背景色就可以了,那具体该怎么做呢?

先说一种比较笨的办法,就是在CxxxxView的OnDraw、OnMoving、OnSizing等等消息响应函数中每次都对上面的客户区窗口设置背景色,具体做法为:
在CxxxxApp中先创建一个成员变量HWND m_hMdiClient(构造函数中初始化为NULL)。然后修改
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
theApp.m_hMdiClient=m_hWndMDIClient; //记录下客户区窗口句柄
……
}
最后在CxxxxView的OnDraw等方法中加上这样的代码:
if(theApp.m_hMdiClient!=NULL)
{
RECT rc;
GetClientRect(theApp.m_hMdiClient,&rc);
HDC hdc=::GetDC(theApp.m_hMdiClient);
HBRUSH hbr=CreateSolidBrush(RGB(0,255,0));
::FillRect(hdc,&rc,hbr);
}
经过这样的修改,感觉上应该是可以了,每当我的子窗口触发重绘等操作时,就把客户区重新填充一下背景,但实际运行你会很失望,程序一创建时,客户区还是灰色的,当触发了重绘操作时,的确客户区变为我想要的绿色了,但每次拖动窗口,就会留下大片的阴影,效果不是一般的差。

有没有什么好的办法呢,其实上面的做法都是在客户区窗口自我绘制完后,又人为的在客户区窗口中重新绘制内容,这是治标不治本的做法,当客户区窗口每次更新时,都默认采用自己的灰色填充窗口背景,这是即时进行的,而我们添加的改变背景的代码则常常不能即时进行,所以,最根本的做法,就是在客户区窗口收到WM_PAINT这样的消息时,不再用默认的灰色填充窗口背景,而是改用我们希望的背景色或图片,写到这里,答案应该是呼之欲出了,那就是定制客户区窗口的默认窗口过程。于是,改动如下:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
theApp.m_hMDIWnd=m_hWndMDIClient;
lpfnOldProc = (WNDPROC)SetWindowLong(m_hWndMDIClient,GWL_WNDPROC,(DWORD)SCWndProc);
……
}
SCWndProc是CMainFrame的静态成员函数:
LRESULT CALLBACK CMainFrame::SCWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
RECT rc;
HBRUSH br;
HDC dc;
switch (wMsg) {
case WM_PAINT:
::GetClientRect(hWnd,&rc);
br=CreateSolidBrush(RGB(0,255,0));
dc=::GetDC(hWnd);
FillRect(dc,&rc,br);
break;
}
return CallWindowProc (lpfnOldProc, hWnd, wMsg, wParam, lParam);
}
别忘了程序关闭前,换回原来的窗口过程:
void CMainFrame::OnDestroy()
{
SetWindowLong(m_hWndMDIClient,GWL_WNDPROC,(DWORD)lpfnOldProc);
CMDIFrameWnd::OnDestroy();
}
这样基本可以了,但程序再一开始启动的时候,窗口背景还是灰色的,这是因为客户区才创建时,我们还没有为其指定新的窗口过程,补救的办法也简单,就是在CxxxxApp::InitInstance()的最后pMainFrame->UpdateWindow();代码之后,加上下面的代码:
RECT rc;
GetClientRect(m_hWndMDIClient,&rc);
HDC hdc=::GetDC(m_hWndMDIClient);
HBRUSH hbr=CreateSolidBrush(RGB(0,255,0));
::FillRect(hdc,&rc,hbr);
好了,基本上这样就差不多了,最后贴一张最终的效果图:

定制MFC多文档窗口的主框架背景相关推荐

  1. MFC单文档之给主窗口添加背景图片

    MFC单文档之给主窗口添加背景图片 1.导入图片 选择一个bmp格式的图片,将其导入到res文件夹中,然后工程资源目录下导入此图,注意格式一定要确定是百分百bmp格式的,不然报错,有的图片很坑是假bm ...

  2. VS2019/MFC编程入门——文档、视图和框架:分割窗口

    上一节中讲了文档.视图和框架结构中各对象之间的关系,本节主要讲讲在MFC中如何分割窗口.在内容开始前为大家介绍一款MFC界面开发控件: Xtreme Toolkit Pro | 免费下载:是屡获殊荣的 ...

  3. vs2010c语言窗口程序,VS2010/MFC编程入门之四十一(文档、视图和框架:分割窗口)...

    上一节中鸡啄米讲了文档.视图和框架结构中各对象之间的关系,本节主要讲讲在MFC中如何分割窗口. 分割窗口概述 分割窗口,顾名思义,就是将一个窗口分割成多个窗格,在每个窗格中都包含有视图,或者是同一类型 ...

  4. 【数字图像处理】 二.MFC单文档分割窗口显示图片

    本文是讲述<数字图像处理>系列文章,继上篇讲述BMP格式图片和显示后,该篇讲述如何对单文档进行分割.主要是采用CSplitterWnd静态分割窗口显示图片等相关知识.本文主要结合自己的课程 ...

  5. MFC使用OpenCV在文档窗口中显示图像(支持多图片格式)

    MFC使用OpenCV在文档窗口中显示图像     [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/72550659 在VS ...

  6. 给多文档窗口添加背景图片

    VC是一个功能强大的可视化的开发工具,但是用VC做的标准界面与Windows一样色彩灰 暗单调,例如多文档窗口应用程序中的主框架窗口的背景便是如此.那么能否给主框架窗 口的背景改变一下色彩或是给主框架 ...

  7. MFC 多文档中同时打开多个文档

    MFC多文档中的打开继承自CWinAppEx中的函数OnFileOpen(),这一点在CXXX.cpp中可以看到.比如如下: [cpp] view plain copy // CCVMFCApp BE ...

  8. VS2010-MFC(文档、视图和框架:分割窗口)

    转自:http://www.jizhuomi.com/software/226.html 上一节讲了文档.视图和框架结构中各对象之间的关系,本节主要讲讲在MFC中如何分割窗口. 分割窗口概述      ...

  9. MFC 学习笔记(一):MFC单文档程序运行流程梳理与总结

    MFC 学习笔记(一):MFC单文档程序运行流程梳理与总结 1.MFC单文档程序运行流程 1.首先利用全局变量对象 theApp 启动应用程序 (这是因为这个全局对象,基类CWinApp中 this ...

最新文章

  1. 2021年大数据Spark(二十五):SparkSQL的RDD、DF、DS相关操作
  2. HTML5 文件域+FileReader 读取文件并上传到服务器(三)
  3. Knative 基本功能深入剖析:Knative Serving 的流量灰度和版本管理
  4. 网页禁用鼠标右键和复制功能兼容方式
  5. 看奥运之二:现场看男子体操团体决赛
  6. Consider defining a bean of type ‘java.lang.String‘ in your configuration
  7. Pandas创建DataFrame对象的几种常用方法
  8. 代码查看工具_不好用打我 | 六个前端开发在线工具推荐
  9. 计算机网络第三版周舸答案,计算机网络技术基础第3版周舸第一章节计算机网络基础知识课件教学.ppt...
  10. 经典的850棋牌游戏搭建教学
  11. Qt QPainter绘图
  12. IDEA鼠标光标变黑块问题解决
  13. KDD 2022 | 美团技术团队精选论文解读
  14. 基于51单片机的蓝牙小车制作【新手向
  15. Anaconda详细安装及使用教程
  16. 网络原理4 数据链路层
  17. 推特情感分析-基于spark
  18. 爬虫之使用代理ip爬取
  19. oracle密码带@!,oracle的密码中带@符号
  20. 解决FIFO读写位宽不等的问题

热门文章

  1. 大数据:广州租房信息统计,这些地方最便宜
  2. echarts漏斗图
  3. mac c语言 转win,C ++跨平台开发(Windows和Mac OS)
  4. 澳洲网:英语水平跟不上 赴澳留学生遭遇“拦路虎”
  5. 表单时间选择/设置默认时间
  6. Selenium简单安装
  7. Scratch基础(五):画多边形
  8. uniapp开发app下载模板功能
  9. 仓管平面图(自定义布局)
  10. 分析自己遇到的Excel导出报NullpointException问题