目录
1. 在 MFC 对话框工程基础上,添加两个MFC CFormView 类
2. 在 CDlgTabLowLevel 对话框(A) 类的头文件中添加下面代码
3. 在 CDlgTabLowLevel 对话框(A) 类的.cpp文件中添加下面代码
应用场景介绍
将对话框 A (CDlgTabLowLevel)拆分成窗格 B(CRegDesView) 和 窗格 C(CRegSetView),注意 B 和 C 的基类必须是某种 view 类,比如 CFormView 或 CTreeView 类,而 A 的基类不能是 view 类,可以是 CDialog 类或 CFrameWnd 类。
1. 在 MFC 对话框工程基础上,添加两个MFC CFormView 类
上面步骤完成后,可以看到类视图中添加了两个类的类文件
另外,资源视图中自动添加了两个类对应的资源对话框
2. 在 CDlgTabLowLevel 对话框(A) 类的头文件中添加下面代码
CDlgTabLowLevel 头文件中添加 CFrameWnd 对象指针和 CSplitterWnd 对象
public:
CFrameWnd* m_pMyFrame; // 为 split dialog 新建的 CFrameWnd 对象指针
CSplitterWnd m_cSplitter; // split 对象
3. 在 CDlgTabLowLevel 对话框(A) 类的.cpp文件中添加下面代码
添加新建 view 类(窗格 B,C)的头文件, CRegSetView.h 和 CRegDesView.h
因为写这个文档时用的工程是之前已经添加过其它窗格的工程,所以下面的代码不止有CRegSetView,CRegDesView窗格,还有其它两个窗格。
重实现 CDlgTabLowLevel 类的 OnCreate, OnSize 和 OnDestory 函数
OnCreate 中代码如下:
// TODO: Add your specialized creation code here
// Because the CFRameWnd needs a window class, we will create a new one. I just copied the sample from MSDN Help.
// When using it in your project, you may keep CS_VREDRAW and CS_HREDRAW and then throw the other three parameters.
//需要注册窗口类
CString strMyClass = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW,
::LoadCursor(NULL, IDC_ARROW), (HBRUSH) ::GetStockObject(WHITE_BRUSH),
::LoadIcon(NULL, IDI_APPLICATION));
// Create the frame window with "this" as the parent
m_pMyFrame = new CFrameWnd;
m_pMyFrame->Create(strMyClass, _T(""), WS_CHILD, CRect(0, 0, 1000, 800), this);
m_pMyFrame->ShowWindow(SW_SHOW);
// and finally, create the splitter with the frame as the parent
m_cSplitter.CreateStatic(m_pMyFrame, 2, 2); //在Frame里切分视图窗口为2×2,就是两行两列
m_cSplitter.CreateView(0, 0, RUNTIME_CLASS(CRegNameView), CSize(800, 500), NULL);//第一行一列
m_cSplitter.CreateView(0, 1, RUNTIME_CLASS(CDisplayView), CSize(200, 500), NULL);//第一行二列
m_cSplitter.CreateView(1, 0, RUNTIME_CLASS(CRegSetView), CSize(500, 300), NULL);//第一行一列
m_cSplitter.CreateView(1, 1, RUNTIME_CLASS(CRegDesView), CSize(500, 300), NULL);//第一行二列
OnSize 中代码如下:
// TODO: Add your message handler code here
CRect cRect;
GetWindowRect(&cRect);
ScreenToClient(&cRect);
m_pMyFrame->MoveWindow(&cRect);
m_pMyFrame->ShowWindow(SW_SHOW);
OnDestroy 中代码如下:
// TODO: Add your message handler code here
if (m_pMyFrame) delete m_pMyFrame;
4. 运行后效果如下(下面两个窗格是本次添加的)
上述操作参考:
MFC对话框窗口分割/拆分_在行进路上的博客-优快云博客_mfc基于对话框分割窗口
5. 拆分各窗格间互发消息
各窗格间发送消息,首先要获取接收消息窗格的句柄,拆分窗格(如上面的 B 和 C)句柄的获取,需要两个要素:父窗口(如上面个的 A)的指针,并把它转化成 CSplitterWnd 类型;GetPane() 函数的使用,通过GetPane()返回拆分窗格的指针,也必须转化成该窗格自身 View 类型后才能获得改窗格的句柄。
拆分窗格句柄获取的代码如下:
//GetPane能够获得所需要句柄分割的那一半
//CDPView是要获得句柄的那一个视图
CSplitterWnd *ps = (CSplitterWnd*) GetParent();
CDPView*pv = (CDPView*)(ps->GetPane(0,0));
pv->m_hWnd;
上面代码结合实际做的工程分析:
上面第一行代码特别重要,首先要获得执行拆分窗口(A)的指针,本工程中是通过 this->GetParent()->GetParent() 实现的;
然后要将拆封窗口的指针强制转化成 CSplitterWnd* 类型,如下图红框代码这个特别关键,比如本例拆分窗口A(CDlgTabLowLevel) 是个对话框类,用 GetParent() 获得的指针是 CWnd 类型的,而后面能调用 GetPane() 函数的指针必须是 CSplitterWnd 类型的;
接下来要看你实际拆分窗口后,分配给窗格的是什么 view 类型,就要用对应的 view 类型指针来接收,比如本例(B 和 C)是 CFormView 类型,如下图红框下面的代码,用 CFormView* 来接收;
最后获取拆分窗格指针要用 GetPane()函数,GetPane() 函数的第一个参数代表行数,第二个参数代表列数,GetPane() 就是返回参数指定的第几行第几列窗格的指针。
上图就是获取拆分窗格句柄,并发送消息的实例,该工程路径:
6. 附加内容 GetParent() 的使用
多层类嵌套获取某个对话框的指针方法:
使用 this->GetParent(), GetParent() 返回的是上层类的指针,注意不是父类的指针,是多层嵌套中上一层的指针。
如上例中的类嵌套关系是 CDlgTabLowLevel -> CRegNameView -> CMySuperGrid, 上面图片中的 OnControlLButtonDown 函数是 CMySuperGrid 的成员函数,所以 this 指针是 CMySuperGrid 对象的指针; this->GetParent() 就是 CMySuperGrid 的上一层 CRegNameView 的指针,尽管 CMySuperGrid 的父类并不是 CRegNameView;同样 this->GetParent()->GetParent() 就是 CDlgTabLowLevel 的指针。