基于单文档的窗口分割
简介部分是对于MFC应用程序的介绍,在博客上看到的,觉得受益匪浅,所以写到这里。
不需要的朋友可以从第二部分程序设计开始看起。
目录
基于单文档的窗口分割 (1)
简介 (3)
MFC应用程序类型简介 (3)
单文档与多视图 (5)
单文档多视图程序设计 (6)
Step1:创建单文档的MFC程序 (6)
Step2:声明相关的变量。
(6)
Step3:重载OnCreateClient()函数,进行窗口的分割 (7)
Step4:设置行列初始值 (9)
附:代码 (10)
简介
MFC应用程序类型简介
在Microsoft VC++ 6.0中,基于MFC的应用程序一般分为以下几种:
多文档界面(MDI)
单文档界面(SDI)
基于对话框的应用程序。
图1-1 应用程序类型
其中单文档又可分为单视图的和多视图的。
图1-2 单文档单视图
图1-3 单文档多视图
一般情况下,单文档仅需要单视图就够了,如Windows自带的记事本、画图程序等等,但
在一些情况下,单文档需要多视图支持,比如同时观察文档的不同部分,同时从不同的角度观察同一文档等。
在MFC的框架下,文档对象(CDocument)有一个保存其所有视图的列表,并提供了增加视图(AddView)与删除视图(RemoveView)函数,以及当文档内容改变时通知其所有视图的方法(UpdateAllViews)。
1-4 类视图
通过多文档框架的窗口复制机制和单文档框架的分割窗口机制是实现单文档多视图的主要方法。
单文档与多视图
一般地,单文档与多视图有三种情况:
1)在多文档界面MDI中,每个视图位于MDI的一个独立子文档框架中,视图对象基于同一个视图类。
用户可以通过“窗口|新窗口”菜单,为同一文档的视图再创建一个窗口,通过新创建的窗口,可以编辑和观察文档的另一部分,同一文档各个视图之间自动实现同步,用户修改一个视图的内容,在另外的视图中也自动更新。
MFC框架通过复制原来的子框架窗口和其中的视图来实现上面的功能,并且是完全自动的。
2)视图对象基于同一视图类,所有视图位于同一文档框架中。
分割窗口将单文档窗口的视图区分割成几个独立的视图,框架从同一视图类创建多个视图对象。
Word的子窗口即属于这种类型。
3)视图对象基于不同的视图类,所有的视图位于同一文档框架中。
多个视图共享同一文档框架,但从不同的视图类创建,每个视图可以为文档提供不同的观察和编辑方法。
比如在一个窗口里观察文档的不同部分,或者是在一个窗口里用不用类型的视图观察同一个文档。
这种类型的实现方法是通过重载框架类CMainFrame的成员函数OnCreateClient实现,用户可以根据不同需要将窗口分为垂直或水平的多个分割窗口。
单文档多视图程序设计
下面通过实例设计,介绍单文档多视图的窗口分割(上面介绍的第二种情况)。
Step1:创建单文档的MFC程序
创建一个基于MFC的应用程序,程序类型选择“单文档”,命名为“SplitterTest”。
Step2:声明相关的变量。
在MainFrm.h中添加如下变量声明。
public:
CSplitterWnd m_miansplitter;
CSplitterWnd m_leftSplitter;
CSplitterWnd m_rightSplitter;
CSplitterWnd m_leftbottom;
BOOL m_isSplitter;
并在CMainFrame的构造函数中,初始化isSplitter为FALSE
Step3:重载OnCreateClient()函数,进行窗口的分割
图2-1重载OnCreateClient()函数
在OnCreateClient()函数中添加如下代码:
这时,运行程序,会发现窗口已经被分割为多视图。
但是,需要拖动一下才显示出来。
图2-2 初步运行结果Step4:设置行列初始值
重载OnSize函数。
图2-3 重载OnSize函数在函数中添加如下代码,
此时,运行结果正常。
图2-4 最终运行结果
附:代码
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) {
// TODO: 在此添加专用代码和/或调用基类
//窗口的分割
if(m_mainsplitter.CreateStatic(this,1,2)==FALSE)
{
return FALSE;
}
if(m_leftsplitter.CreateStatic(&m_mainsplitter,2,1,WS_CHILD|WS_VISIBLE, m_mainsplitter.IdFromRowCol(0,0))==FALSE)
{
return FALSE;
}
if(m_rightsplitter.CreateStatic(&m_mainsplitter,1,2,WS_CHILD|WS_VISIBLE, m_mainsplitter.IdFromRowCol(0,1))==FALSE)
{
return FALSE;
}
if(m_leftbottom.CreateStatic(&m_leftsplitter,1,2,WS_CHILD|WS_VISIBLE, m_leftsplitter.IdFromRowCol(1,0))==FALSE)
{
return FALSE;
}
m_isSplitter = TRUE;
//绑定视图
CRect cRect;
GetClientRect(&cRect);
if(m_leftsplitter.CreateView(0,0,RUNTIME_CLASS(CSplitterTestView), CSize(cRect.Width()/2,cRect.Height()/2),pContext)==FALSE) {
return FALSE;
}
if(m_rightsplitter.CreateView(0,0,RUNTIME_CLASS(CSplitterTestView), CSize(cRect.Width()/4,cRect.Height()),pContext)==FALSE) {
return FALSE;
}
if(m_rightsplitter.CreateView(0,1,RUNTIME_CLASS(CSplitterTestView), CSize(cRect.Width()/4,cRect.Height()),pContext)==FALSE) {
return FALSE;
}
if(m_leftbottom.CreateView(0,0,RUNTIME_CLASS(CSplitterTestView), CSize(cRect.Width()/4,cRect.Height()/2),pContext)==FALSE) {
return FALSE;
}
if(m_leftbottom.CreateView(0,1,RUNTIME_CLASS(CSplitterTestView), CSize(cRect.Width()/4,cRect.Height()/2),pContext)==FALSE) {
return FALSE;
}
return TRUE;
/*return CFrameWnd::OnCreateClient(lpcs, pContext);*/
}
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
CRect crFram;
GetClientRect(&crFram);
if(m_isSplitter)
{
m_mainsplitter.SetColumnInfo(0,crFram.Width()/2,10);
m_leftsplitter.SetRowInfo(0,crFram.Height()/2,10);
m_rightsplitter.SetColumnInfo(0,crFram.Width()/4,10);
m_rightsplitter.SetColumnInfo(1,crFram.Width()/4,10);
m_mainsplitter.RecalcLayout();
}
}。