简单的拆分器, 使用 CWnd 派生窗格






4.96/5 (34投票s)
2004 年 2 月 24 日
4分钟阅读

231141

8971
一个分割器窗口类,它结合了 CSplitterWnd 的基本功能和专业外观,并能够使用 CWnd 派生窗格
引言
是的,这是又一个分割器窗口类。那么,为什么在有这么多类似类的情况下,我还要发布一个新类呢?答案很简单。 IMHO,CodeProject 上的所有分割器窗口类都可以分为两类:
- 一类是继承自原始 MFC
CSplitterWnd
的。它们外观漂亮,为经典的CSplitterWnd
提供了很多优势,但继承自CSplitterWnd
会限制你只能在其中使用CView
派生的窗口。 - 另一类是,我可以用于各种窗口 - 但当我编译并测试它们时,它们看起来不像
CSplitterWnd
那么漂亮。
在这篇文章中,我提供了一个不继承自 CSplitterWnd
的类。它允许你使用简单的 CWnd
派生窗口。但它结合了原始 CSplitterWnd
的专业外观。一些例程我从 MFC 源代码中获取。请在阅读本文时多包涵。这是我在 CodeProject 的第一篇文章 : ) 。
特点
我在 CSimpleSplitterWnd
设计中的目标是模拟 CSplitterWnd
的基本功能。使用这个类,你可以将多个窗格水平或垂直排列。它不提供自动分割、共享滚动条和交错跟踪器。我发现它们不太有用 - 但如果足够多的人需要,我可以添加其中一些功能。 :) CSimpleSplitter
(与 CSplitterWnd
相比) 的想法是,窗格窗口是相互独立的,因此它们也负责自己的滚动和边框。
Using the Code
分割器的布局在构造函数中设置
CSimpleSplitter(int nPanes, UINT nOrientation = SSP_HORZ,
int nMinSize = 30, int nBarThickness = 3);
nPanes
是窗格的数量,nOrientation
应该是 SSP_HORZ
或 SSP_VERT
。nMinSize
是任何窗格的最小高度(或宽度)- 当你调整分割器大小时,这对于重新计算布局算法很重要。nBarThickness
是窗格之间条的宽度或高度。所有这些属性在分割器实例的生命周期内保持固定。分割器及其窗格的创建非常直接
BOOL Create(CWnd* pParent, UINT nID = AFX_IDW_PANE_FIRST);
BOOL CreatePane(int nIndex, CWnd* pPaneWnd, DWORD dwStyle,
DWORD dwExStyle, LPCTSTR lpszClassName = NULL);
窗格的索引是从 0
到 nPanes - 1
。参数 dwStyle
, dwExStyle
和 lpszClassName
会传递给 pPaneWnd->CreateEx()
(如果你想将创建的窗口绑定到窗格,请使用 SetPane
代替)。例如,你可以在那里指定窗格的边框。在演示应用程序中,“大”窗格具有 WS_EX_CLIENTEDGE
扩展样式,而三个“平坦”窗格具有 WS_EX_STATICEDGE
扩展样式。分割条本身只是一个灰色矩形,所以如果你不指定任何边框并为窗格窗口设置灰色背景,你也可以在对话框中使用该分割器。
以下五个方法类似于 CSplitterWnd
方法,因此不需要特别说明。
int GetPaneCount() const;void SetPane(int nIndex, CWnd* pPaneWnd);
CWnd* GetPane(int nIndex) const;
virtual void SetActivePane(int nIndex);
CWnd* GetActivePane(int* pIndex) const;
但是,设置窗格的宽度或高度使用了不同的技术
void SetPaneSizes(const int* sizes);
你传递一个包含 nPanes
个整数的数组。它们指定窗格的相对大小。你可以使用任何比例,窗格会根据数组成员的总和成比例调整大小。当你调整整个分割器的大小时,窗格的大小会与其实际大小成比例改变。如果需要,它们会被调整到 m_nMinSize
。
void GetPaneRect(int nIndex, CRect& rcPane) const;
void GetBarRect(int nIndex, CRect& rcBar) const;
使用这些函数,你可以检索分割器客户区域坐标中窗格的位置。条的索引从 1
到 nPanes - 1
。
就是这样了。看看 SimpleSplitterApp
演示,特别是 CMainFrame::OnCreate
代码,你就会明白一切了!
关注点
在我编写分割器时,我对框架如何重绘调整大小的窗口感到困惑。如果你调整顶部或左侧边框的大小,框架首先只会在相应方向上移动窗口内容,然后它会调用 OnPaint()
。这样窗口就会被重绘两次,在分割器中这看起来很丑。
幸运的是,有一个消息处理函数 CWnd::OnWindowPosChanging
。如果你看到 SWP_NOCOPYBITS
消息(如你在 CSimpleSplitter
和 CChildWnd
代码中看到的),你可以避免初始内容的移动。我认为这在分割器之外的其他许多情况下都很有用。
历史
- 2004 年 2 月 11 日 - 发布第一个版本
- 2004 年 3 月 24 日 - 修复了一些错误(参见下面的消息)。在
SetPaneSizes
函数中,现在你应该只传递相对大小,而不是绝对大小。
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。