显示同一文档的多个同时视图

如何说服 MFC Doc/View 架构让我同时显示同一文档的两个不同视图?

How do I persuade the MFC Doc/View architecture to let me simultaneously display two different views of the same document?

例如,假设我的 CDocument 子类表示某个描述的存档.
我想要一个 UI,其中该存档中所有条目的名称都显示在左侧窗格的 CListView 子类中,而当前选定条目的详细信息显示在 右侧窗格中的 CEditView 子类.

For example, say my CDocument sub-class represents an archive of some description.
I want a UI where the names of all the entries in that archive are presented in a CListView sub-class in the left hand pane, while the details of the currently selected entry are displayed in a CEditView sub-class in the right hand pane.

CSingleDocTemplate 似乎只允许连接一个文档、一个框架和一个视图.我仍然想要一个 SDI 应用程序,但我想要一个文档和两个不同的视图 - 这不就是一个好的 Doc/View 架构的全部意义吗?

The CSingleDocTemplate only seems to allow for connecting up one document, one frame and one view. I still want an SDI application, but I want one document and two different views - isn't that the whole point of a good Doc/View architecture?

推荐答案

SDI 意思是Single Document Interface",它限制你一次只能有一个文档,但不限制查看次数您可以打开此文档.

SDI means "Single Document Interface", it restricts you to only one single document at a time but not in the number of views you can open for this document.

在 SDI 应用程序中打开多个视图可能最常用的方法是 Splitter Windows.

The probably most common approach to open multiple views in an SDI application are Splitter Windows.

您将一个视图添加到 CSingleDocTemplate (不管是哪一个)

You add one view to the CSingleDocTemplate (it doesn't matter which one)

pDocTemplate = new CSingleDocTemplate(
    IDR_MYRESOURCEID,
    RUNTIME_CLASS(CMyDoc),
    RUNTIME_CLASS(CMyFrameWnd),
    RUNTIME_CLASS(CMyListView));

你的框架窗口获得了一个 CSplitterWnd m_wndSplitter 的实例并且你重载了 OnCreateClient 虚函数:

Your frame window gets an instance of a CSplitterWnd m_wndSplitter and you overload the OnCreateClient virtual function:

BOOL CMyFrameWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
{
    VERIFY(m_wndSplitter.CreateStatic(this,1,2)); // one row / two columns

    VERIFY(m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyListView),
        CSize(300,300),pContext));
    VERIFY(m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMyEditView),
        CSize(300,300),pContext));

    return TRUE;
}

本示例创建一个包含一行两列的拆分窗口.拆分器的左侧是 CMyListView 类型的视图,右侧是 CMyEditView 类型的视图.

This example creates a splitter window with one row and two columns. On the left side in the splitter is a view of type CMyListView and on the right side is a view of type CMyEditView.

您甚至可以将多个拆分器窗口相互嵌套,以在框架窗口中创建任意复杂的视图集合.

You can even nest multiple splitter windows one in each other to create arbitrary complex view collections in the frame window.

这是一个小教程,展示了如何在 SDI 应用程序中使用拆分器窗口:

Here is a small tutorial which shows how to work with splitter windows in a SDI application:

http://www.codeproject.com/KB/splitter/splitterwindowtutorial.aspx

编辑

将您添加到拆分器的视图与文档在内部进行 MFC 的连接:传递给 OnCreateClientCCreateContext* pContext 包含一个引用 m_pCurrentDoc 到当前文件(Framewindow 知道这个文件).MFC 在 CView::OnCreate (ViewCore.cpp) 中使用它来将视图添加到文档中:m_pCurrentDoc->AddView(this) 并设置文档指针 <代码>m_pDocument 在视图中.

Wiring up of the views you add to the splitter with the document does MFC internally: CCreateContext* pContext which is passed into OnCreateClient contains a reference m_pCurrentDoc to the current document (the Framewindow knows about this document). MFC uses this in CView::OnCreate (ViewCore.cpp) to add the View to the Document: m_pCurrentDoc->AddView(this) and to set the document pointer m_pDocument in the View.

因此,随后对文档的 UpdateAllViews 调用将处理这两个视图.

Therefore subsequent calls of UpdateAllViews of your document will take care of both views.

相关文章