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::SetRowInfo 和 CSplitterWnd::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”。