显示同一文档的多个同时视图
Displaying multiple simultaneous Views of the same Document
我如何说服MFC文档/视图架构让我同时显示同一文档的两个不同视图?
例如,假设我的CDocument
子类表示一些描述的存档。
我想要一个UI,在该存档中的所有条目的名称都呈现在左侧窗格的CListView
子类中,而当前选择的条目的详细信息显示在右侧窗格的CEditView
子类中。
CSingleDocTemplate
似乎只允许连接一个文档,一个框架和一个视图。我仍然想要一个SDI应用程序,但是我想要一个文档和两个不同的视图——这难道不是一个好的文档/视图架构的全部意义吗?
SDI意思是"单个文档接口",它限制你一次只能打开一个文档,但不限制你可以为这个文档打开的视图的数量。
在SDI应用程序中打开多个视图最常见的方法可能是Splitter Windows。你添加一个视图到CSingleDocTemplate
(这并不重要)
pDocTemplate = new CSingleDocTemplate(
IDR_MYRESOURCEID,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMyFrameWnd),
RUNTIME_CLASS(CMyListView));
你的框架窗口得到一个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应用程序中使用拆分器窗口:
http://www.codeproject.com/KB/splitter/splitterwindowtutorial.aspx编辑
将您添加到拆分器的视图与文档连接在一起在内部执行MFC: CCreateContext* pContext
传递给OnCreateClient
,其中包含对当前文档的引用m_pCurrentDoc
(Framewindow知道这个文档)。MFC在CView::OnCreate
(ViewCore.cpp)中使用此方法将视图添加到文档:m_pCurrentDoc->AddView(this)
并在视图中设置文档指针m_pDocument
。
因此,随后调用文档的UpdateAllViews
将照顾这两个视图。
根据注释修改:
好的,你需要的是一个静态拆分器窗口。最简单的方法(我知道)是创建一个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);
这是我们需要改变的——Create
是创建动态拆分器的。我们需要摆脱它,并创建一个静态拆分器。第一步是创建另一个视图类——现在,我们只有一个视图类,但我们想要两个,每个窗格一个。
创建第二个视图类最简单的方法(据我所知)是运行第二个VS副本,并创建另一个(单独的)应用程序。我们将告诉它基于CListView
的应用程序的视图类。然后,我们将获取该视图的文件,并将它们添加到原始项目中。为了便于连接,我们希望确保第二个项目使用与第一个项目相同的名称作为其文档类。
OnCreateClient
,用下面的代码替换上面引用的代码:
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"在下窗格,但(我认为)它应该是相当明显的改变,使重新安排视图。
当然,从那里开始,你必须在每个视图中编写代码来做视图应该做的事情——但是由于每个视图仍然是一个独立的、正常的视图,每个视图都是合理独立的,所以开发就像正常一样。唯一显著的区别是必须遵循使文档无效的规则,并且(特别是如果其中一个视图的更新成本很高)您可能需要考虑使用提示来告诉哪些部分的数据已经无效,这样您可以编写每个视图只更新需要的部分,而不是每次都重新绘制所有数据。- 正在查找文档以获得PS4平台的C++中的设备信息
- 如何在文档文件夹中创建目录
- 当Microsoft文档仅包含 C# 示例时,如何查找 C++ 包含文件名
- 通过构造函数创建一些值并尝试添加到文档中使用 rapidjson 不起作用
- 关于类的 Python 文档 - 对C++的引用不正确
- C++/autoconf 等效于文档库要求.txt的要求是什么?
- mbed:使用 USB 文档库编译会导致错误
- C++ VISUAL STUDIO:GLFWwindow没有初始化,即使它是在文档中编写的并且以前工作过
- MFC MDI 向文档添加第二个视图
- 关于在模型/视图Qt文档中排序的描述可能是错误的
- 对 MFC 文档视图的列表视图进行子类化
- MFC文档/视图体系结构-创建没有初始视图的文档
- 使用文档/视图分隔(MFC)填充组合框
- c++ MFC MDI如何根据活动文档更改类视图显示的内容
- 通过MFC文档/视图架构创建winsock客户端
- 非动态文档/视图架构在MFC中的使用
- Boost::序列化和MFC文档/视图体系结构
- 如何截取视图的屏幕截图并将图片插入MS-Word文档中
- 如何在 MFC 中使用文档/视图体系结构
- 显示同一文档的多个同时视图