Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 显示同一文档的多个同时视图_C++_Visual Studio_Model View Controller_Mfc - Fatal编程技术网

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

C++ 显示同一文档的多个同时视图,c++,visual-studio,model-view-controller,mfc,C++,Visual Studio,Model View Controller,Mfc,如何说服MFC文档/视图体系结构允许我同时显示同一文档的两个不同视图 例如,假设myCDocument子类表示某种描述的存档。 我想要一个UI,在该UI中,存档中所有条目的名称显示在左侧窗格中的CListView子类中,而当前所选条目的详细信息显示在右侧窗格中的CEditView子类中 CSingleDocTemplate似乎只允许连接一个文档、一个框架和一个视图。我仍然想要一个SDI应用程序,但我想要一个文档和两个不同的视图-这不是一个好的文档/视图体系结构的全部要点吗?根据评论进行修订: 好

如何说服MFC文档/视图体系结构允许我同时显示同一文档的两个不同视图

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


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

根据评论进行修订:

好的,你要的是一个静态分割窗口。创建此窗口的最简单方法(据我所知)是从SDI MFC项目开始,并告诉它您想要一个拆分器窗口(在AppWizard的“用户界面功能”下,选中“拆分窗口”)。这将创建一个动态拆分器——也就是说,它只从一个窗格开始,您可以通过拖动拆分器栏来创建第二个窗格——但是当您这样做时,您只会得到两个相同的视图(尽管您可以分别滚动它们)

然后我们需要做一些工作,把它从一个动态拆分器变成一个静态拆分器。最好从动态拆分器的代码开始。如果您查看该应用程序的
CMainFrame
,您会发现它有:

CSplitterWnd m_wndSplitter;
如果查看主框架的
OnCreateClient
,您会发现如下内容:

return m_wndSplitter.Create(this,
    2, 2,               // TODO: adjust the number of rows, columns
    CSize(10, 10),      // TODO: adjust the minimum pane size
    pContext);
CRect rect;
GetClientRect(&rect);

BOOL ret = m_wndSplitter.CreateStatic(this, 2, 1); // 2 rows, 1 column of views

    // row 0, column 0 will be the "OriginalView". The initial split will be 
    // in half -- i.e., each pane will be half the height of the frame's client
    //
m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(OriginalView), CSize(1, rect.Height()/2), pContext);
m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(ListBasedView), CSize(1, rect.Height()/2), pContext);
这就是我们需要改变的-
Create
就是创建动态拆分器的地方。我们需要去掉它,而是创建一个静态拆分器。第一步是创建另一个视图类——现在,我们只有一个视图类,但我们需要两个,每个窗格一个

据我所知,创建第二个视图类的最简单方法是运行VS的第二个副本,然后创建另一个(单独的)应用程序。我们将告诉它将该应用程序的视图类基于
CListView
。然后,我们将获取该视图的文件,并将它们添加到原始项目中。为了便于连接,我们希望确保第二个项目使用与第一个项目相同的文档类名称

在这一点上,我们有第二个视图的代码,但它没有连接到其他任何东西,因此它创建的视图将不可见。为了使其可见,我们需要将其标题包含到CMainframe.cpp(或目标项目中的任何名称)中。然后,我们回到
OnCreateClient
,并将上面引用的代码替换为如下内容:

return m_wndSplitter.Create(this,
    2, 2,               // TODO: adjust the number of rows, columns
    CSize(10, 10),      // TODO: adjust the minimum pane size
    pContext);
CRect rect;
GetClientRect(&rect);

BOOL ret = m_wndSplitter.CreateStatic(this, 2, 1); // 2 rows, 1 column of views

    // row 0, column 0 will be the "OriginalView". The initial split will be 
    // in half -- i.e., each pane will be half the height of the frame's client
    //
m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(OriginalView), CSize(1, rect.Height()/2), pContext);
m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(ListBasedView), CSize(1, rect.Height()/2), pContext);
目前,我已经创建了一个水平拆分,上面的窗格中有“OriginalView”,下面的窗格中有“ListBaseView”,但是(我认为)应该很明显要对视图进行哪些更改来重新排列

当然,从那时起,您必须在每个视图中编写代码,以执行该视图应该执行的任何操作--但是由于每个视图仍然是一个独立的、正常的视图,因此每个视图都是合理独立的,因此开发与正常开发差不多。唯一显著的区别是,您必须遵循使文档无效的规则,并且(特别是在其中一个视图更新成本很高的情况下)您可能需要考虑使用提示来判断数据的哪个部分已经失效,这样您就可以编写每个视图来更新所需的内容,而不是每次只重新绘制所有的数据。

SDI表示“单文档接口”,它限制您一次只能打开一个文档,但不限制为此文档打开的视图数

在SDI应用程序中打开多个视图的最常见方法可能是拆分窗口

将一个视图添加到
CSingleDocTemplate
(哪一个视图无关紧要)

您的框架窗口获取了一个
CSplitterWnd m_wndSplitter
的实例,您重载了
OnCreateClient
虚拟函数:

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
的视图

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

以下是一个小教程,演示如何在SDI应用程序中使用拆分器窗口:

编辑

将添加到拆分器中的视图与文档关联在内部进行MFC:
CCreateContext*pContext
传递到
OnCreateClient
中,其中包含对当前文档的引用
m_pCurrentDoc
(框架窗口了解此文档)。MFC在
CView::OnCreate
(ViewCore.cpp)中使用它将视图添加到文档中:
m_pccurrentdoc->AddView(this)
,并在视图中设置文档指针
m_pDocument


因此,随后对文档的
updatealView
调用将同时处理两个视图。

注意:我看到了,但重点是能够在两个或多个视图之间切换,而不是同时显示两个视图。这是我讨厌微软工具的一点——当你完全按照设想的方式做事时,它们非常棒,但是站在队伍外面,砰!事情变得困难了一个数量级。谢谢@Slauma,这听起来正是我需要的。但有一件事我有点困惑。您可以说“将一个视图添加到CSingleDoctTemplate(哪一个视图无关紧要)”。这将告诉文档一个视图,但是文档如何了解其他视图呢?i、 e.对于调用
CDocument::updatealView()
GetNextView()