TN029:拆分窗口

本说明介绍 MFC CSplitterWnd 类,该类提供窗口拆分功能并管理其他窗格窗口的大小调整。

拆分样式

CSplitterWnd 支持两种不同样式的拆分窗口。

在“静态拆分”中,在创建拆分窗口时它将创建窗格。 窗格的顺序和数量不会更改。 拆分条用于调整不同窗格的大小。 可以使用此样式在每个窗格中显示不同的视图类。 Visual C++ 图形编辑器和 Windows 文件管理器程序使用的是这种拆分样式。 这种拆分窗口不使用拆分框。

在“动态拆分”中,用户拆分和取消拆分新视图时会创建并销毁其他窗格。 这种拆分以单个视图开始,并提供拆分框供用户启动拆分。 当在一个方向拆分视图时,拆分窗口动态创建新的视图对象。 这个新视图对象表示新窗格。 如果使用键盘界面在两个方向拆分视图,拆分窗口将为三个新窗格创建三个新视图对象。 拆分处于活动状态时,Windows 会将拆分框显示为窗格之间的拆分条。 当用户删除拆分时,Windows 销毁其他视图对象,但原始视图会保留直到拆分窗口本身被销毁。 Microsoft Excel 和 Microsoft Word 应用程序使用的就是动态拆分样式。

创建任何一种拆分窗口时,必须指定通过拆分可以管理的最大行数和列数。 静态拆分创建的窗格会填充所有行和列。 创建 CSplitterWnd 时,动态拆分仅创建第一个窗格。

可以为静态拆分指定的最大窗格数为 16 行 x 16 列。 推荐如下配置:

  • 1 行 x 2 列:窗格通常不同

  • 2 行 x 1 列:窗格通常不同

  • 2 行 x 2 列:窗格通常相似

可以为动态拆分指定的最大窗格数为 2 行 x 2 列。 推荐如下配置:

  • 1 行 x 2 列:用于列数据

  • 2 行 x 1 列:用于文本或其他数据

  • 2 行 x 2 列:用于网格或表的数据

拆分示例

许多 MFC 示例程序直接或间接使用拆分窗口。 MFC 常规示例 VIEWEX 介绍了静态拆分的数个用法,包括如何将拆分器放在拆分器中。

你还可使用 ClassWizard 创建包含拆分窗口的新多文档界面 (MDI) 子框架窗口类。 有关拆分窗口的详细信息,请参阅多文档类型、视图和框架窗口

实现使用的术语

下面是特定于拆分窗口的术语列表:

CSplitterWnd:窗口,它提供拆分窗格的控件以及行或列上在所有窗格之间共享的滚动条。 使用从零开始的数字指定行和列(第一个窗格是行 = 0,列 = 0)。

窗格:CSplitterWnd 管理的特定于应用程序的窗口。 窗格通常是派生自 CView 类的对象,但可以是具有相应子窗口 ID 的任何 CWnd 对象。

若要使用派生自 CWnd 的对象,请将对象的 RUNTIME_CLASS 传递给 CreateView 函数,就像使用派生自 CView 的类时做的那样。 类必须使用 DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE,因为框架在运行时使用动态创建。 尽管 CSplitterWnd 中有很多特定于 CView 类的代码,但在执行这些操作之前,始终使用 CObject::IsKindOf

拆分条:位于窗格行和列之间的控件。 它可用于调整窗格的行或列的大小。

拆分框:动态 CSplitterWnd 中的控件,可用于创建窗格的新行或列。 它位于垂直滚动条顶部或水平滚动条左侧。

拆分交点:垂直拆分条和水平拆分条的交点。 可以拖动它来同时调整窗格行和列的大小。

共享滚动条

CSplitterWnd 类还支持共享滚动条。 这些滚动条控件是 CSplitterWnd 的子元素,并与拆分器中的不同窗格共享。

例如,在 1 行 x 2 列窗口中,可以在创建 CSplitterWnd 时指定 WS_VSCROLL。 Windows 创建在两个窗格之间共享的特殊滚动条控件。

[      ][      ][^]
[pane00][pane01][|]
[      ][      ][v]

当用户移动滚动条时,将 WM_VSCROLL 消息发送到这两个视图。 当任一视图设置滚动条位置时,设置共享滚动条。

请注意,共享滚动条对类似的视图对象最有用。 如果在拆分器中混合了不同类型的视图,则可能需要编写特殊代码来协调其滚动位置。 如果任何派生自 CView 的类使用 CWnd 滚动条 API,它将委托给共享滚动条(如果存在)。 CScrollView 实现就是支持共享滚动条的 CView 类。 非派生自 CView 的类、依赖于非控件滚动条的类,或者使用标准 Windows 实现的类(例如 CEditView)不适用于 CSplitterWnd 的共享滚动条功能。

最小大小

每一行都有最小行高,每一列都有最小列宽。 这个最低值保证窗格不至于小到无法完全显示。

对于静态拆分窗口,初始最小行高和列宽为 0。 对于动态拆分窗口,初始最小行高和列宽由 CSplitterWnd::Create 函数的 sizeMin 参数设置

可以使用 CSplitterWnd::SetRowInfoCSplitterWnd::SetColumnInfo 函数更改这些最小大小。

实际大小与理想大小

拆分窗口中窗格的布局取决于包含它们的框架的大小。 当用户调整包含它们的框架的大小时,CSplitterWnd 重新调整窗格的位置和大小,使其尽可能适合框架。

用户可以手动设置行高和列宽,或者程序可以使用 CSplitterWnd 类设置理想的大小。 实际大小可能比理想大小更小或更大。 如果没有足够的空间显示理想大小,或者拆分窗口右侧或底部有过多的空白,Windows 将调整实际大小。

自定义控件

可以重写许多函数以提供自定义行为和自定义界面。 可以重写以下第一个设置,为拆分窗口的各种图形组件提供备用图像。

  • virtual void OnDrawSpltter(CDC* pDC, ESplitType nType, const CRect& rect);

  • virtual void OnInvertTracker(const CRect& rect);

调用此函数以创建共享滚动条控件。 可以重写它以在滚动条旁边创建额外的控件。

  • virtual BOOL CreateScrollBarCtrl(DWORD dwStyle, UINT nID);

这些函数实现动态拆分窗口的逻辑。 你可以重写这些函数,提供更高阶的拆分逻辑。

  • virtual void DeleteView(int row, int col);

  • virtual BOOL SplitRow(int cyBefore);

  • virtual BOOL SplitColumn(int cxBefore);

  • virtual void DeleteRow(int rowDelete);

  • virtual void DeleteColumn(int colDelete);

CView 功能

CView 类使用以下高级命令以委托给 CSplitterWnd 实现。 由于这些命令是虚拟的,因此标准 CView 实现不需要链接整个 CSplitterWnd 实现。 对于使用 CView 而非 CSplitterWnd 的应用程序,CSplitterWnd 实现不会与应用程序链接。

  • virtual BOOL CanActivateNext(BOOL bPrev = FALSE);

    检查 ID_NEXT_PANE 或 ID_PREV_PANE 当前是否可行。

  • virtual void ActivateNext(BOOL bPrev = FALSE);

    执行“下一窗格”或“上一窗格”命令。

  • virtual BOOL DoKeyboardSplit();

    执行键盘拆分命令,通常为“Window Split”。

另请参阅

按编号列出的技术说明
按类别列出的技术说明