CSplitterWnd类分割MFC单文档应用程序窗口

CSplitterWnd类分割MFC单文档应用程序窗口

前言

网上其他大牛已经对MFC窗口分割进行了详细介绍,这里主要用意是分享我在做窗口分割的经验,若是对大家能够有所帮助的话,我倍感荣幸,由于本人水平有限,如若本文中出现错误,望大家见谅与指正!

工具函数

MFC窗口分割的作案工具主要是CSplitterWnd类成员函数CreateStatic()与CreateView(),CreateStatic()函数用于分割窗口,可以利用返回值判断分割是否成功;CreateView()函数用于关联相关的视图类。两个函数的原型为:

 

 
  1. virtual BOOL CreateStatic(

  2. CWnd* pParentWnd,

  3. int nRows,

  4. int nCols,

  5. DWORD dwStyle = WS_CHILD | WS_VISIBLE,

  6. UINT nID = AFX_IDW_PANE_FIRST

  7. );

pParentWnd:父窗口指针,第一次分割指定为this;nRows:分割出来窗口的行数;nCols:分割出来窗口的列数;dwStyle:分割窗口的属性;nID:对于需要再次分割窗口的ID;

 

 
  1. virtual BOOL CreateView(

  2. int row,

  3. int col,

  4. CRuntimeClass* pViewClass,

  5. SIZE sizeInit,

  6. CCreateContext* pContext

  7. );

row:需要关联视图类的行索引(以0开始);col:需要关联视图类的列索引(以0开始);pViewClass:一般通过宏定义的“函数”RUNTIME_CLASS()得到需要关联的视图运行之间类;sizeInit:子窗口的尺寸;pContext:填写OnCreateClient()函数传递进来的环境参数。

 

实现

定义分割窗口类对象,在CMainFrame头文件类定义中定义:

 
  1. CSplitterWnd m_splitwnd;

  2. CSplitterWnd m_subsplitwnd;

对于需要关联的View类可以在CMainFrame头文件类定义中添加相关的声明,添加的同时要添加相关类的头文件,方便进行管理。

 
  1. CsplitwindView* m_psplitwnd;

  2. CDialogView* m_pdialogview;

  3. CDialogSub* m_pdialogsub;

注明:在调试的时候可能会出现如下的错误,需要在相关View类头文件中添加XXXdoc.h,View类xxxdoc.h要在xxxView.h前面。

1>error C2143: 语法错误 : 缺少“;”(在“*”的前面)
1>error C4430: 缺少类型说明符 - 假定为 int。注意:  C++ 不支持默认 int
1>warning C4183: “GetDocument”:  缺少返回类型;假定为返回“int”的成员函数

 

重写 CMainFrame::OnCreateClient()函数进行窗口分割

 
  1. BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

  2. {

  3. // TODO: 在此添加专用代码和/或调用基类

  4. CRect rect;

  5. GetClientRect(&rect);

  6. int nwidth(rect.right);

  7. int nheight(rect.bottom); //获取客户区窗口大小

  8.  
  9. if (!m_splitwnd.CreateStatic(this, 1, 2)) //窗口分割

  10. {

  11. MessageBox(_T("分割窗口错误"), _T("Error"), MB_OK|MB_ICONERROR);

  12. return false;

  13. }

  14.  
  15. //关联相关的View类

  16. m_splitwnd.CreateView(0, 0, RUNTIME_CLASS(CsplitwindView), CSize(nwidth/6*3, nheight), pContext);

  17. m_psplitwnd = (CsplitwindView*)m_splitwnd.GetPane(0, 0);

  18.  
  19. //对子窗口进行在分割

  20. if (!m_subsplitwnd.CreateStatic(&m_splitwnd, 2, 1, WS_VISIBLE|WS_CHILD, m_splitwnd.IdFromRowCol(0,1)))

  21. {

  22. MessageBox(_T("子窗口分割窗口错误"), _T("Error"), MB_OK | MB_ICONERROR);

  23. return false;

  24. }

  25. //关联相关的View类

  26. m_subsplitwnd.CreateView(0, 0, RUNTIME_CLASS(CDialogView), CSize(nwidth/6*3, nheight/2), pContext);

  27. m_pdialogview = (CDialogView*)m_subsplitwnd.GetPane(0, 0);

  28.  
  29. m_subsplitwnd.CreateView(1, 0, RUNTIME_CLASS(CDialogSub), CSize(nwidth/6*3, nheight/2), pContext);

  30. m_pdialogsub = (CDialogSub*)m_subsplitwnd.GetPane(1, 0);

  31.  
  32. m_splitwnd.SetActivePane(0, 0);

  33.  
  34. return true;

  35. //return CFrameWnd::OnCreateClient(lpcs, pContext);

  36. }

上面第二次调用CreateStaic()函数是对子窗口的第二次分割,上面关联的CsplitwindView为工程向导创建的,CDialogView与CdialogSub是相关的对话框类,他们的创建步骤为:1.创建相关的对话框资源;2.对话框的属性Style选择为child,border属性选择为none,否则会报错;3.添加对话框类将其派生自CFormView类。

注意:在单文档窗口分割的OnCreateClient()函数中返回值直接返回true,不要返回上面注释类的代码,否则窗口分割不成功。

运行效果如图:

  

对于分割出来的窗口样式问题,可以继承CSplitterWnd类,但是不能直接继承,因为没这个选项,可以继承他的父类CWnd类,再将CWnd改为CSplitterWnd。在修改继承的类中的函数就可以DIY相应的分割窗口风格,至于怎么固定分割窗口的大小,可以使相应的鼠标消息不执行相应的动作即可,也就是没有处理代码。可以参考他的博客

http://blog.csdn.net/robin__chou/article/details/49963575

MFC文档视图框架

在某些情况下可能会在View类中调用Frame类中的函数或变量、Frame类中调用View类中的函数或变量、Frame类中调用Doc类中函数或变量

如:Frame类中调用View类中函数可以使用GetActiveView()函数来获取视图类指针,接着便可以调用相应部分的View类函数和变量。对于Frame中调用Doc类也是一样的道理

CMxxxxView *pView = (CxxxxView*)GetActiveView();

View类中调用Frame类中函数可以使用GetParentFrame()函数来获取窗口类指针,接着便可以调用相应部分的Frame类函数和变量。对于View中调用Doc类也是一样的道理

CMainFrame* pFrame = (CMainFrame*)GetParentFrame();

    因而只要知道View,Frame,Doc,App之间相互访问的关系,就可以利用他们之间的关系,方便地调用相应的类成员变量和函数。