MFC/C++ 窗口大小调整辅助类






4.91/5 (138投票s)
在调整窗口大小时为您提供完全控制

引言
在MFC中,调整控件大小或重新定位控件可能相当麻烦。如果您熟悉.NET平台,使用Control
类的Anchor
和Dock
属性以及用于向容器控件添加子控件的设计时支持,事情会简化得多。我尝试模仿.NET的某些功能,但采用C++的方式。
背景
网上有其他类似的解决方案(也在CodeProject.com上)。我认为我的解决方案在设计、简洁性和功能丰富性方面脱颖而出。
此解决方案允许您执行以下操作
- 锚定对话框控件
- 创建包含其他面板或UI控件的面板
- 通过使用最小尺寸和最大尺寸属性来限制对话框控件或面板的大小
- 通过使用最小尺寸和最大尺寸属性来限制对话框的大小
- 创建水平或垂直分隔容器
- 冻结分隔容器,以便用户无法使用鼠标调整面板大小
- 设置分隔容器的固定面板,以便在对话框调整大小时,固定面板将保持不变
- 设置对话框控件或面板的父级(与Win32
SetParent
API无关) - 使用Visual Style在对话框的右下角显示一个调整大小的抓手(如果应用程序支持)
- 为分隔容器的分隔器显示调整大小的抓手
- 将对话框控件停靠在其父面板内
- 创建流式布局面板
让我们简要看一下.NET是如何调整子控件大小的
Anchor
- 它允许子控件锚定到左、上、右或底部边缘,或这些边缘的任何组合。Dock
- 它允许子控件停靠在左、上、右和底部边缘。- Visual Studio 设计器支持 - 如果您将框架控件放在Windows窗体上,然后将按钮控件拖到框架上,该按钮将成为框架的实际子控件,以及Windows窗体的孙子控件。但在MFC的资源编辑器中,如果您将框架放在对话框模板上,然后将按钮拖到框架控件上,该按钮实际上是对话框模板的直接子控件,而不是框架的子控件。这意味着如果您移动框架,按钮将不会移动。
SplitContainer
- 自该控件发明以来,创建分隔器窗口从未如此简单。它有两个面板,可以容纳其他控件。FlowLayout
- 表示一个动态地水平或垂直排列其内容的面板。
因此,在.NET中,所有控件都是Form
的子控件或孙子控件;这创建了一个控件的层次结构。当父控件的大小被调整或重新定位时,其所有子控件会根据它们的Anchor
或Dock
属性设置进行调整大小或重新定位。
在我的解决方案中,我创建了一个矩形(CRect
)的层次结构。我实现了Anchor
、Panel
、SplitContainer
、Dock
和FlowLayout
的概念。
此解决方案中有几个类,但CWndResizer
是开发人员唯一会使用的类。
通常,您会在Visual Studio资源编辑器中设计对话框模板,然后在对话框类的实现中,您会有一个类似这样的成员变量
private:
CWndResizer m_resizer;
本文随附的示例使用CDialog
类来演示该类的许多功能。但该类可以与任何派生自CWnd
的类一起使用(CDialog
、CPropertyPage
、CPropertySheet
、CFrmWnd
、CFormView
等)。
在此类执行任何操作之前,您必须调用Hook
方法,如下所示
BOOL CExample1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
BOOL bOk = m_resizer.Hook(this);
ASSERT(bOk == TRUE);
}
在本文中,我将把这个窗口(传递给Hook
方法)称为“钩接窗口”。
通过调用此方法,它会将一个窗口过程钩子放在WndProc
链中。
当您调用Hook
方法时,它会将钩接窗口的客户端区域存储在一个名为CPanel
的结构中。面板主要是指在钩接窗口的客户端坐标中给定的矩形区域。一个面板可以有零个或多个子面板。在创建面板时,您为面板指定一个唯一的名称。该名称用于稍后引用面板或查找面板。钩接窗口的客户端区域是层次结构的根,其名称为_root
。
每个面板都有Anchor
、MinSize
和MaxSize
属性(以及其他一些属性)。但您不能直接设置或获取面板的属性;相反,您将使用CWndResizer
类的成员方法。
其思想是,当CPanel
的大小被调整或重新定位时,它的所有子控件也会相对地调整大小和重新定位。
现在,让我们看一些代码片段。
以下代码会将对话框的“确定”和“取消”按钮锚定到右下角
BOOL CExample1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
BOOL bOk = m_resizer.Hook(this);
ASSERT(bOk == TRUE);
bOk = m_resizer.SetAnchor(IDOK, ANCHOR_RIGHT | ANCHOR_BOTTOM);
ASSERT(bOk == TRUE);
bOk = m_resizer.SetAnchor(IDCANCEL, ANCHOR_RIGHT | ANCHOR_BOTTOM);
ASSERT(bOk == TRUE);
}
如果您想创建一个面板并将其Anchor
属性设置为ANCHOR_HORIZONTALLY
,您可以这样做
BOOL CExample1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
BOOL bOk = m_resizer.Hook(this);
ASSERT(bOk == TRUE);
CRect rc(40, 40, 240, 240);
bOk = m_resizer.CreatePanel(_T("MyNewPanel"), &rc);
bOk = m_resizer.SetAnchor(_T("MyNewPanel"), ANCHOR_HORIZONTALLY);
ASSERT(bOk == TRUE);
ASSERT(bOk == TRUE);
}
关于剪裁(重要)
此解决方案无法剪裁对话框控件的任何部分或面板的任何部分。CPanel
对象通常不关联任何窗口(HWND
)。如果子面板比其父面板大,则子面板在父面板外部的区域将可见,因为父面板和子面板都不是实际的窗口。为了规避此问题,我们应该通过调用SetMinimumSize
方法设置父面板的合理最小尺寸,以便父面板永远不会小于子面板的最小尺寸。您还应该考虑设置钩接窗口的最小尺寸,以便它能够包含其客户端区域内的所有面板。
Using the Code
在VS2008中创建的示例应用程序演示了该类的许多功能。
CWndResizer
类具有以下成员
以下是详细信息
方法 |
|
|||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
描述 | 在钩接窗口的客户端区域创建流式布局面板(.NET类比)。 | |||||||||||||||||||||||||
参数 | panelName |
此面板的唯一名称。此名称用于稍后引用此面板。 | ||||||||||||||||||||||||
prcPanel |
在钩接窗口的客户端坐标中给出的矩形。 | |||||||||||||||||||||||||
parrID |
对话框控件ID的数组。此方法将创建面板,其区域是指定数组中的对话框控件的组合区域。 | |||||||||||||||||||||||||
setAsChildren |
如果为TRUE ,则此方法将为parrID 中指定的每个对话框控件创建面板,并使其成为其自身的子控件。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 -或-
-或-
|
|||||||||||||||||||||||||
备注 |
您可以通过调用 其他面板可以是 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 在钩接窗口的客户端区域创建面板。 | |||||||||||||||||||||||||
参数 | panelName |
此面板的唯一名称。此名称用于稍后引用此面板。 | ||||||||||||||||||||||||
prcPanel |
在钩接窗口的客户端坐标中给出的矩形。 | |||||||||||||||||||||||||
parrID |
对话框控件ID的数组。此方法将创建面板,其区域是指定数组中的对话框控件的组合区域。 | |||||||||||||||||||||||||
setAsChildren |
如果为TRUE ,则此方法将为parrID 中指定的每个对话框控件创建面板,并使其成为其自身的子控件。 |
|||||||||||||||||||||||||
panelID |
对话框控件的ID。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 -或-
-或-
-或-
|
|||||||||||||||||||||||||
备注 |
创建面板后,默认情况下,它将具有以下初始设置
关于
关于
|
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 创建分隔容器(.NET类比)。 | |||||||||||||||||||||||||
参数 | splitContainerName |
此分隔容器的唯一名称。此名称用于稍后引用此面板。 | ||||||||||||||||||||||||
panelNameA |
通过先前调用CWndResizer::CreatePanel 或CWndResizer::CreateSplitContainer 创建的面板的名称。如果结果面板是水平分隔容器,则此参数指向分隔容器的左面板。否则,它是分隔容器的顶面板。 |
|||||||||||||||||||||||||
panelIDA |
钩接窗口的子控件(窗口)的ID。 如果结果面板是水平分隔容器,则此参数指向分隔容器的左面板。否则,它是分隔容器的顶面板。 |
|||||||||||||||||||||||||
panelNameB |
通过先前调用 如果结果面板是水平分隔容器,则此参数指向分隔容器的右面板。否则,它是分隔容器的底面板。 |
|||||||||||||||||||||||||
panelIDB |
钩接窗口的子控件(窗口)的ID。 如果结果面板是水平分隔容器,则此参数指向分隔容器的右面板。否则,它是分隔容器的底面板。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 -或-
-或- 指定的面板(矩形)发生重叠。 -或- 一个或所有指定的面板已被用于创建分隔容器。 |
|||||||||||||||||||||||||
备注 |
如果第一个矩形(第二个参数)的 CSplitContainer的定义
如果您将鼠标移到
|
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 获取指定面板的锚定(.NET类比)。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
anchor |
接收锚定值。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。anchor 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 检索面板的锚定值。有关详细信息,请参阅SetAnchor 。 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 获取CWndResizer 是否自动处理绘制。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。anchor 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 请参阅SetAutoHandlePaint 以获取详细信息。 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 获取指定面板的锚定(.NET类比)。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
uDock |
接收停靠值。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。anchor 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 检索面板的停靠值。有关详细信息,请参阅SetDock 。 |
|||||||||||||||||||||||||
方法 | BOOL GetFixedPanel(LPCTSTR splitContainer, short & panel); |
|||||||||||||||||||||||||
描述 | 获取固定面板的名称(如果有)(.NET类比)。 | |||||||||||||||||||||||||
参数 | splitContainerName |
通过先前调用CWndResizer::CreateSplitContainer 创建的分隔容器的名称。 |
||||||||||||||||||||||||
panel |
接收固定面板的ID。如果包含1,则左侧面板(或垂直分隔容器的顶部面板)是固定的,如果包含2,则右侧面板(或垂直分隔容器的底部面板)是固定的。否则,splitContainer 没有固定面板。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。panel 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 检索分隔容器的固定面板ID。有关详细信息,请参阅SetSetFixedPanel 。 |
|||||||||||||||||||||||||
方法 | BOOL GetFlowDirection(LPCTSTR flowPanelName, short & direction); |
|||||||||||||||||||||||||
描述 | 获取FlowPanel 的流方向(.NET类比)。 |
|||||||||||||||||||||||||
参数 | flowPanelName |
通过先前调用CWndResizer::CreateFlowLayoutPanel 创建的分隔容器的名称。 |
||||||||||||||||||||||||
direction |
接收FlowPanel 的流方向。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。direction 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 请参阅SetFlowDirection 以获取详细信息。 |
|||||||||||||||||||||||||
方法 | BOOL GetFlowItemSpacingX(LPCTSTR flowPanelName, int & nSpace); |
|||||||||||||||||||||||||
描述 | 获取FlowPanel 中x方向的项之间的间距。 |
|||||||||||||||||||||||||
参数 | flowPanelName |
通过先前调用CWndResizer::CreateFlowLayoutPanel 创建的分隔容器的名称。 |
||||||||||||||||||||||||
nSpace |
接收以像素为单位的间距。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。panel 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 请参阅SetFlowItemSpacingX 以获取详细信息。 |
|||||||||||||||||||||||||
方法 | BOOL GetFlowItemSpacingY(LPCTSTR flowPanelName, int & nSpace); |
|||||||||||||||||||||||||
描述 | 获取FlowPanel 中y方向的项之间的间距。 |
|||||||||||||||||||||||||
参数 | flowPanelName |
通过先前调用CWndResizer::CreateFlowLayoutPanel 创建的分隔容器的名称。 |
||||||||||||||||||||||||
nSpace |
接收以像素为单位的间距。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。panel 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 请参阅SetFlowItemSpacingY 以获取详细信息。 |
|||||||||||||||||||||||||
方法 | BOOL GetIsSplitterFixed(LPCTSTR splitContainerName , BOOL &fixed); |
|||||||||||||||||||||||||
描述 | 获取分隔容器的分隔器是否设置为固定(.NET类比)。 | |||||||||||||||||||||||||
参数 | splitContainerName |
通过先前调用CWndResizer::CreateSplitContainer 创建的分隔容器的名称。 |
||||||||||||||||||||||||
fixed |
接收一个布尔值。如果为TRUE ,则分隔器是固定的;否则,分隔器可以自由地通过鼠标移动。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。fixed 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 检索一个标志,该标志指示分隔容器的分隔器是否可以自由地通过鼠标移动。有关详细信息,请参阅SetIsSplitterFixed 。 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 获取指定面板的最大尺寸(.NET类比)。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。size 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 如果panelName 或panelID 引用的是水平分隔容器的面板,则应忽略CSize::cy 成员。如果panelName 或panelID 引用的是垂直分隔容器的面板,则应忽略CSize::cx 成员。 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 获取指定面板的最小尺寸(.NET类比)。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。size 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略size 值。尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 如果panelName 或panelID 引用的是水平分隔容器的面板,则应忽略CSize::cy 成员。如果panelName 或panelID 引用的是垂直分隔容器的面板,则应忽略CSize::cx 成员。 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 获取指定面板的父级名称。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
parentName |
接收父级的名称。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。parentName 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 如果parentName 为_root ,则表示该面板是钩接窗口的直接子级。 |
|||||||||||||||||||||||||
方法 | BOOL GetShowResizeGrip(); |
|||||||||||||||||||||||||
描述 | 获取一个标志,指示是否在钩接窗口的右下角绘制调整大小的抓手。 | |||||||||||||||||||||||||
参数 | N/A |
无参数。 | ||||||||||||||||||||||||
返回值 | TRUE |
它将在对话框/窗口的右下角绘制一个调整大小的抓手。 | ||||||||||||||||||||||||
FALSE |
它将不在对话框/窗口的右下角绘制调整大小的抓手。 | |||||||||||||||||||||||||
备注 | 此方法从不失败。 | |||||||||||||||||||||||||
方法 | BOOL GetShowSplitterGrip(LPCTSTR splitContainerName, BOOL & bShow); |
|||||||||||||||||||||||||
描述 | 获取分隔容器的分隔器抓手是否可见。 | |||||||||||||||||||||||||
参数 | splitContainerName |
通过先前调用CWndResizer::CreateSplitContainer 创建的分隔容器的名称。 |
||||||||||||||||||||||||
bShow |
接收一个布尔值。如果为TRUE ,则分隔器抓手可见;否则,分隔器抓手隐藏。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | N/A | |||||||||||||||||||||||||
方法 | BOOL Hook(CWnd * pWnd); |
|||||||||||||||||||||||||
描述 | 将钩子放入WndProc 链中。 |
|||||||||||||||||||||||||
参数 | pWnd |
指向您要调整大小的CWnd 及其子控件的指针。 |
||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。
-或- 此方法已调用一次。 |
|||||||||||||||||||||||||
备注 |
在调用任何其他方法之前,您必须调用此方法。
|
|||||||||||||||||||||||||
方法 | BOOL InvokeOnResized(); |
|||||||||||||||||||||||||
描述 | 模拟钩接窗口的大小调整。 | |||||||||||||||||||||||||
参数 | N/A |
无参数。 | ||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 |
|||||||||||||||||||||||||
备注 |
此方法向钩接窗口发送 在创建了必要的面板并设置了锚定之后,您可能希望调用此方法来初始应用设置。 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 设置指定面板的锚定(.NET类比)。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
anchor |
锚定值。请参阅备注。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。anchor 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 |
注意:面板永远不会小于其允许的最小尺寸,也不会大于其允许的最大尺寸。 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 |
设置CWndResizer 是否自动处理绘制。 |
|||||||||||||||||||||||||
参数 | bHandle |
如果CWndResizer 要自动处理WM_PAINT消息,则为TRUE ;否则为FALSE 。 |
||||||||||||||||||||||||
返回值 | TRUE |
始终返回TRUE | ||||||||||||||||||||||||
FALSE |
从不返回FALSE。 | |||||||||||||||||||||||||
备注 | 这是一个例子。BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
BOOL bOk = FALSE;
bOk = m_resizer.Hook(this);
ASSERT( bOk);
// turning off auto paint handle
m_resizer.SetAutoHandlePaint(FALSE);
m_resizer.SetShowResizeGrip(TRUE);
bOk = m_resizer.InvokeOnResized();
ASSERT( bOk);
return TRUE;
}
void CTestDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// Your custom drawing
CRect rect(10, 20, 60, 60);
CBrush brush(RGB(0,0,0));
dc.FillRect(rect, &brush);
// call CWndResizer::Draw method so it can draw
// any classes derived from CVisualPanel
m_resizer.Draw(&dc); // <= calling Draw method
}
|
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 设置指定面板的停靠(.NET类比)。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
uDock |
停靠值。请参阅备注。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 |
|
|||||||||||||||||||||||||
方法 | BOOL SetFixedPanel(LPCTSTR splitContainerName, short panel); |
|||||||||||||||||||||||||
描述 | 设置分隔容器的一个面板为固定(.NET类比)。 | |||||||||||||||||||||||||
参数 | splitContainerName |
通过先前调用CWndResizer::CreateSplitContainer 创建的分隔容器的名称。 |
||||||||||||||||||||||||
panel |
固定面板的ID。如果包含1,则左侧面板(或垂直分隔容器的顶部面板)是固定的,如果包含2,则右侧面板(或垂直分隔容器的底部面板)是固定的。否则,splitContainer 没有固定面板。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 |
|||||||||||||||||||||||||
备注 |
随着钩接窗口的大小被调整,固定面板保持不变,而另一个面板会调整大小。 注意:面板永远不会小于其允许的最小尺寸,也不会大于其允许的最大尺寸。 |
|||||||||||||||||||||||||
方法 | BOOL SetFlowDirection(LPCTSTR flowPanelName, short direction); |
|||||||||||||||||||||||||
描述 | 设置FlowPanel 的流方向(.NET类比)。 |
|||||||||||||||||||||||||
参数 | flowPanelName |
通过先前调用CWndResizer::CreateFlowLayoutPanel 创建的分隔容器的名称。 |
||||||||||||||||||||||||
direction |
FlowPanel 的流方向。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 将direction 设置为1表示从左到右的方向,任何其他值都表示从上到下的方向。 |
|||||||||||||||||||||||||
方法 | BOOL SetFlowItemSpacingX(LPCTSTR flowPanelName, int nSpace); |
|||||||||||||||||||||||||
描述 | 设置FlowPanel 中x方向项之间的间距。 |
|||||||||||||||||||||||||
参数 | flowPanelName |
通过先前调用CWndResizer::CreateFlowLayoutPanel 创建的分隔容器的名称。 |
||||||||||||||||||||||||
nSpace |
以像素为单位的间距。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 如果流方向是从左到右,则nSpace 表示x方向上两个项之间的间距,否则表示项的两个列之间的间距。 |
|||||||||||||||||||||||||
方法 | BOOL SetFlowItemSpacingY(LPCTSTR flowPanelName, int & nSpace); |
|||||||||||||||||||||||||
描述 | 获取FlowPanel 中y方向的项之间的间距。 |
|||||||||||||||||||||||||
参数 | flowPanelName |
通过先前调用CWndResizer::CreateFlowLayoutPanel 创建的分隔容器的名称。 |
||||||||||||||||||||||||
nSpace |
以像素为单位的间距。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。应忽略 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 如果流方向是从左到右,则nSpace 表示y方向上两个项之间的间距,否则表示项的两个行之间的间距。 |
|||||||||||||||||||||||||
方法 | BOOL SetIsSplitterFixed(LPCTSTR splitContainerName , BOOL fixed); |
|||||||||||||||||||||||||
描述 | 设置分隔容器的分隔器是否设置为固定(.NET类比)。 | |||||||||||||||||||||||||
参数 | splitContainerName |
通过先前调用CWndResizer::CreateSplitContainer 创建的分隔容器的名称。 |
||||||||||||||||||||||||
fixed |
一个布尔值。如果为TRUE ,则分隔器是固定的;否则,分隔器可以自由地通过鼠标移动。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 |
|||||||||||||||||||||||||
备注 | 如果分隔器设置为固定,用户将无法使用鼠标移动分隔器。 | |||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 设置指定面板的最大尺寸(.NET类比)。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
size |
面板的最小尺寸。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 如果panelName 或panelID 引用的是水平分隔容器的面板,则应忽略size 的cy 成员。如果panelName 或panelID 引用的是垂直分隔容器的面板,则应忽略size 的cx 成员。 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 设置指定面板的最小尺寸(.NET类比)。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 如果panelName 或panelID 引用的是水平分隔容器的面板,则应忽略size 的cy 成员。如果panelName 或panelID 引用的是垂直分隔容器的面板,则应忽略size 的cx 成员。 |
|||||||||||||||||||||||||
方法 |
|
|||||||||||||||||||||||||
描述 | 设置指定面板的父级名称。 | |||||||||||||||||||||||||
参数 | panelName |
通过先前调用CWndResizer::CreatePanel 创建的面板的名称。 |
||||||||||||||||||||||||
panelID |
钩接窗口的子控件(窗口)的ID。 | |||||||||||||||||||||||||
parentID |
父级的名称。 | |||||||||||||||||||||||||
parentName |
父级的名称。 | |||||||||||||||||||||||||
返回值 | TRUE |
成功。parentName 包含有效值。 |
||||||||||||||||||||||||
FALSE |
失败。应忽略size 值。尚未调用 -或-
|
|||||||||||||||||||||||||
备注 |
这不应被视为Win32 将 |
|||||||||||||||||||||||||
方法 | void SetShowResizeGrip(BOOL show = TRUE); |
|||||||||||||||||||||||||
描述 | 设置一个标志,指示是否在钩接窗口的右下角绘制调整大小的抓手。 | |||||||||||||||||||||||||
参数 | show |
如果应绘制调整大小的抓手,则为TRUE ;否则为FALSE 。 |
||||||||||||||||||||||||
返回值 | N/A |
无返回值。 | ||||||||||||||||||||||||
备注 | 此方法从不失败。 | |||||||||||||||||||||||||
方法 | BOOL SetShowSplitterGrip(LPCTSTR splitContainerName, BOOL bShow); |
|||||||||||||||||||||||||
描述 | 设置一个标志,指示是否显示分隔容器分隔器的抓手。 | |||||||||||||||||||||||||
参数 | splitContainerName |
通过先前调用CWndResizer::CreateSplitContainer 创建的分隔容器的名称。 |
||||||||||||||||||||||||
bShow |
如果应绘制调整大小的抓手,则为TRUE ;否则隐藏。 |
|||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 -或-
|
|||||||||||||||||||||||||
备注 | 此方法从不失败。 | |||||||||||||||||||||||||
方法 | BOOL Unhook(); |
|||||||||||||||||||||||||
参数 | N/A |
无参数。 | ||||||||||||||||||||||||
返回值 | TRUE |
成功。 | ||||||||||||||||||||||||
FALSE |
失败。 尚未调用 |
|||||||||||||||||||||||||
备注 |
您不必调用此方法。 当钩接窗口收到 |
关注点
此解决方案不需要您自己计算任何数字。此解决方案将所有功能封装在CWndResizer
中。
可以对其进行重新设计,使其暴露其他对象(CPanel
、CSplitContainer
等)。我这样设计的原因是我不希望用户了解太多的对象,并简化内存的分配和释放。
另一件事是它依赖于MFC类(CWnd
等);同样,您可以删除所有对MFC类的引用,并使用纯Win32 API。
历史
- 2011年1月13日:文章已更新,包含新功能
Docking
和FlowLayoutPanel
- 2011年2月25日:根据成员 2272507 的评论,更改了
CWndResizer::UnHook
方法 - 2011年3月16日:更新了演示和源代码
- 2011年5月23日:更新了演示和源代码
- 2011年8月1日:更新了演示和源代码
- 2011年8月17日:更新了演示和源代码 - 现在支持
CFormView
上的滚动 - 2011年12月7日:更新了演示和源代码
- 2013年1月25日:添加了新示例(示例11)并修复了一个错误
- 2013年6月28日:更新了源代码
- 2013年11月9日:在用户报告后,修复了示例9中的错误
- 2014年10月20日:添加了三个新方法:
Draw(CPaintDC * pDC)
、GetAutoHandlePaint()
和SetAutoHandlePaint(BOOL bHandle)
。这些在您自定义绘制时很有帮助。有关详细信息,请参阅上面的文档。 - 2014年10月20日:修复了报告的错误