单文档、多文档浅析 [一]

废话不多说,直切主题。(以下的示例说明均以MDI作为叙述)

整个程序就相当于一个 文档模板[CSingleDocTemplate/CMultiDocTemplate]列表,单文档就是只有一个模板,多文档就是有多个模板。

一个模板就包括:菜单[Menu]、文档[Doc]、框架[Frame]、视图[View]

注意,他们是一个整体。

看一下代码:

CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_MDI_TETYPE, // 菜单资源ID RUNTIME_CLASS(CMDI_testDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame

 RUNTIME_CLASS(CMDI_testView)); AddDocTemplate(pDocTemplate); // 放到模板列表中

当使用VC自动生成的代码时,编译运行,使用菜单“开始”->“新建”,会从模板列表中选择一个模板进行创建一个“整体”,最初的话,会自动生成一个新的窗口,因为最初只有一个文档模板(“整体”),所以,它自动就生成了一个。注意菜单ID,它是子框架的菜单,它与ChildFrame绑定在一起了。我们可以通过关闭所有的View窗口,就可以观察到菜单改变了,MainFrame主框架和ChildFrame在默认的情况下,它们的菜单是不同的。

请做试验:添加一个菜单,响应该菜单函数,代码就是创建一个新的模板,并加入到列表:

CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_MDI_TETYPE, RUNTIME_CLASS(CMDI_testDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame

 RUNTIME_CLASS(CMDI_testView)); AddDocTemplate(pDocTemplate);

再通过“开始”->“新建”,这个时候,你会不会发现,这个时候,就会有两个模板供你选择了,因为你已经又创建了一个模板。如下图:

 单文档、多文档浅析 [一]

说完了他们一个整体性,接下来,我们就来说说一个整体中,各个部件的关系。

1)框架 (Frame)是视图和文档的载体,视图是一个窗口,文档则不是窗口,视图是要显示在框架中的。我们看一下窗口父子关系:

单文档、多文档浅析 [一]

从上面这两幅图对比,可以看出,视图“sfdjk”的父窗口是“MDIClient”即是类CChildFrame[它从CMDIClientWnd派生出来]的对象。

2)视图是显示文档数据的窗口。这里可以看出,文档负责管理数据,视图负责将文档中的数据显示出来。我们可以看下视图OnDraw的代码:

void CMDI_testView::OnDraw(CDC* pDC) { CMDI_testDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here

}

通过GetDocument就获取了文档的指针,然后就能去文档中取数据,并在OnDraw中显示出来。我们要知道的是,视图View是有一个文档Document的指针的,这便是对应关系了。[文档并不需要一个视图指针,因为数据便是数据,它不需要去关心谁去显示它,但是事实上,它保存有与它关联的视图指针]

很多时候,我们一个文档可以会包含有多份不同类别的数据,而又想用不同的窗口显示不同类别的数据,这个时候,可以创建多个视图,一个文档是可以包含多个视图的。然后在程序中处理好视图的切换即可。我们创建一个新的视图时,如何与文档关联起来呢?见代码[主框架中,而非子框架中]:

// 文档和视图关联

 CDocument* m_pDoc = ((CFrameWnd*)m_pMainWnd)->GetActiveDocument(); // 这里为什么要获取活动的文档呢?
// 因为主框架有可能含有多个模板,就有可能有多个文档[因为一个模板有一个文档就足够了,多出的文档有可能是其它模板的]
// 所以要获取活动的文档 CCreateContext context; context.m_pCurrentDoc
= m_pDoc; // 创建视图 UINT nIDFORANOTHERVIEW = AFX_IDW_PANE_FIRST + 1; CRect rect; m_pAnotherView->Create(
  NULL,
  NULL,
  WS_CHILD,
  rect,
  ((CFrameWnd*)m_pMainWnd)->GetActiveFrame (),
  nIDFORANOTHERVIEW,
  &context);

通过 CCreateCContext对象进行关联。注意:因为框架是视图和文档的载体,所以框架有必要提供接口:获取活动文档、获取活动视图 [这里要注意,文档和视图虽然是对应关系,或者说有一定的包含关系,但它们并不能互相管理对方,它们只能由框架(Frame)进行统一管理]。

视图既然是显示在框架上的,那二者又如何关联起来呢?见代码:

CChildFrame * pFrm = new CChildFrame();// 框架可以是你新建或者定制的框架类

 CCreateContext context; context.m_pNewViewClass = RUNTIME_CLASS(CDemoView);// 视图可以是你想显示的视图 // context.m_pCurrentDoc = m_pDoc;// m_pDoc 就是你要关联到的文档对象 // 也可以进行文档的关联

 pFrm->LoadFrame(IDR_TEST2TYPE,WS_CHILD|WS_OVERLAPPEDWINDOW, this, &context);// 菜单资源你可以修改

 pFrm->ShowWindow(SW_SHOW);// 显示窗口

 pFrm->InitialUpdateFrame(NULL,true);// 调用视图的 OnInitialUpdate ()和框架的 ActiveFrame (),你可以在这里设置窗口的标题 

 最后来说一下他们之间的关系。

Frame框架可以:

1)获取活动的Frame框架[如果没有子框架,就返回它自己]

2)获取活动的文档

2)获取/设置活动的视图

 

Document文档可以:

1)获取Frame框架

2)增加/删除视图

3)更新视图

4)设备所有从该文档生成的Frame框架的标题

 

View视图可以:[就它最可怜]

1)获取它所关心的文档

 

 参考资料:http://blog.163.com/hzxjtx@126/blog/static/356533742009121105752954/

你可能感兴趣的:(文档)