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

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (34投票s)

2004 年 2 月 24 日

4分钟阅读

viewsIcon

231141

downloadIcon

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_HORZSSP_VERTnMinSize 是任何窗格的最小高度(或宽度)- 当你调整分割器大小时,这对于重新计算布局算法很重要。nBarThickness 是窗格之间条的宽度或高度。所有这些属性在分割器实例的生命周期内保持固定。分割器及其窗格的创建非常直接

BOOL Create(CWnd* pParent, UINT nID = AFX_IDW_PANE_FIRST);
BOOL CreatePane(int nIndex, CWnd* pPaneWnd, DWORD dwStyle,   
 DWORD dwExStyle, LPCTSTR lpszClassName = NULL);

窗格的索引是从 0nPanes - 1。参数 dwStyle, dwExStylelpszClassName 会传递给 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;

使用这些函数,你可以检索分割器客户区域坐标中窗格的位置。条的索引从 1nPanes - 1

就是这样了。看看 SimpleSplitterApp 演示,特别是 CMainFrame::OnCreate 代码,你就会明白一切了!

关注点

在我编写分割器时,我对框架如何重绘调整大小的窗口感到困惑。如果你调整顶部或左侧边框的大小,框架首先只会在相应方向上移动窗口内容,然后它会调用 OnPaint()。这样窗口就会被重绘两次,在分割器中这看起来很丑。

幸运的是,有一个消息处理函数 CWnd::OnWindowPosChanging。如果你看到 SWP_NOCOPYBITS 消息(如你在 CSimpleSplitterCChildWnd 代码中看到的),你可以避免初始内容的移动。我认为这在分割器之外的其他许多情况下都很有用。

历史

  • 2004 年 2 月 11 日 - 发布第一个版本
  • 2004 年 3 月 24 日 - 修复了一些错误(参见下面的消息)。在 SetPaneSizes 函数中,现在你应该只传递相对大小,而不是绝对大小。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.