选项卡式MDI框架窗口






2.95/5 (9投票s)
一个带标签的框架窗口,用于在单个框架中显示文档的多个视图。

引言
在最近的一个项目中,我想使用不同的视图来显示文档数据。 我不喜欢默认的 MFC 实现,它为每个视图创建一个新的框架窗口。
我去了Code Project,找到了一些带标签的窗口文章(属性表视图,一个多文档标签界面等),但没有一个完全符合我的需求:每个文档一个框架,每个视图一个标签。 在 Google 的一点帮助下,我找到了 CodeGuru 上的一篇名为“带标签的视图”的旧文章,作者是 Salvatore Mosaico。 我采用了最初的想法,删除了分组功能,并创建了这个类,增加了对另一个我需要的功能的支持:子框架中的工具栏和状态栏。
Using the Code
- 从
CTabbedMDIChildWnd
派生一个新类。 如果手动执行此操作,请记住定义消息映射和动态创建。 您可以使用类向导为您完成这项脏活。- 选择一个新的 MFC 类
- 选择
CMDIChildWnd
作为基类 - 并将所有出现的
CMDIChildWnd
替换为我们的类。 在 *.h 和 *.cpp 文件中都执行此操作 - 不要忘记在 *.h 中包含
CTabbedMDIChildWnd
头文件。
#include "TabbedMDIChildWnd.h"
- 选择一个新的 MFC 类
- 包含视图的头文件
#include "FirstView.h" #include "SecondView.h"
- 要告诉框架窗口使用哪些标签,请使用辅助类
CTabbedMDIChildWnd::CTabItem
。 此类派生自TCITEM
,并添加了一个CRuntimeClass
来创建视图。 您可以在下一个示例中使用提供的构造函数。 - 覆盖
OnCreateClient
。 在函数内部,定义标签,并调用基类
BOOL CDemoChildWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { // this is the heart of the class, each call to DefineView will // add a tab of the specified class DefineTab(CTabbedMDIChildWnd::CTabItem(_T("First View"), RUNTIME_CLASS(CFirstView))); DefineTab(CTabbedMDIChildWnd::CTabItem(_T("Second View"), RUNTIME_CLASS(CSecondView))); return CTabbedMDIChildWnd::OnCreateClient(lpcs,pContext); }
- 您的类现在已准备就绪。 现在是编译项目的最佳时机!
- 下一步是在应用程序的
InitInstance
函数中更改 MDI 子框架
// Register the application's document templates. Document templates // serve as the connection between documents, frame windows and views CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_TabbedFrameTYPE, RUNTIME_CLASS(CTabbedFrameDoc), RUNTIME_CLASS(CDemoChildWnd), // custom MDI child frame RUNTIME_CLASS(CTabbedFrameView)); AddDocTemplate(pDocTemplate);
在类内部
该类有一个 CTabCtrl
成员,并为通过调用 DefineTab
定义的每个视图创建一个标签。 它处理 TCN_SELCHANGE
和 TCN_SELCHANGING
通知消息,以便在选择标签时隐藏和显示视图。
它使用 std::vector
来跟踪使用不同视图的运行时类定义的标签。 此实现施加了一个限制,只支持一个视图类的实例。 使用相同的运行时类多次调用 DefineTab
并不是一个好主意!
如果要更改选项卡控件的外观,可以自定义 CTabbedMDIChildWnd::OnCreateClient
以更改选项卡控件的样式,或者进行额外的调用以添加图像等。
历史
- 1.1 修复了小的内存泄漏(感谢 J.H.Park)
- 2008 年 3 月 12 日:更新下载