65.9K
CodeProject 正在变化。 阅读更多。
Home

选项卡式MDI框架窗口

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.95/5 (9投票s)

2004年5月1日

CPOL

2分钟阅读

viewsIcon

126742

downloadIcon

3229

一个带标签的框架窗口,用于在单个框架中显示文档的多个视图。

Sample Image - screenshot.png

引言

在最近的一个项目中,我想使用不同的视图来显示文档数据。 我不喜欢默认的 MFC 实现,它为每个视图创建一个新的框架窗口。

我去了Code Project,找到了一些带标签的窗口文章(属性表视图一个多文档标签界面等),但没有一个完全符合我的需求:每个文档一个框架,每个视图一个标签。 在 Google 的一点帮助下,我找到了 CodeGuru 上的一篇名为“带标签的视图”的旧文章,作者是 Salvatore Mosaico。 我采用了最初的想法,删除了分组功能,并创建了这个类,增加了对另一个我需要的功能的支持:子框架中的工具栏和状态栏。

Using the Code

  • CTabbedMDIChildWnd 派生一个新类。 如果手动执行此操作,请记住定义消息映射和动态创建。 您可以使用类向导为您完成这项脏活。
    • 选择一个新的 MFC 类

    • 选择 CMDIChildWnd 作为基类

    • 并将所有出现的 CMDIChildWnd 替换为我们的类。 在 *.h*.cpp 文件中都执行此操作

    • 不要忘记在 *.h 中包含 CTabbedMDIChildWnd 头文件。
      #include "TabbedMDIChildWnd.h"
  • 包含视图的头文件
    #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_SELCHANGETCN_SELCHANGING 通知消息,以便在选择标签时隐藏和显示视图。

它使用 std::vector 来跟踪使用不同视图的运行时类定义的标签。 此实现施加了一个限制,只支持一个视图类的实例。 使用相同的运行时类多次调用 DefineTab 并不是一个好主意!

如果要更改选项卡控件的外观,可以自定义 CTabbedMDIChildWnd::OnCreateClient 以更改选项卡控件的样式,或者进行额外的调用以添加图像等。

历史

  • 1.1 修复了小的内存泄漏(感谢 J.H.Park)
  • 2008 年 3 月 12 日:更新下载
© . All rights reserved.