GroupControl






4.72/5 (28投票s)
CButton 派生控件,用于协助使用分组框。
引言
CGroupControl
是一个 CButton
派生的类,它有助于使用分组框(即具有 BS_GROUPBOX
样式的按钮)。CGroupControl
可以轻松地启用/禁用、显示/隐藏或移动一个组。组的父控件不需要任何代码,因为这会在组控件本身启用/禁用、显示/隐藏或移动时自动完成。该控件还包含一个机制,允许您对组中的每个控件执行任何操作。
如何使用
使用 CGroupControl
类非常简单。按照以下步骤将其添加到现有项目中。
- 将源代码文件(GroupControl.cpp 和 GroupControl.h)放入您希望使用的目录后,将这些文件添加到您的 Visual Studio 项目中。
- 在资源编辑器中,根据需要添加一个分组框,并为其指定一个不同于默认
IDC_STATIC
的 ID。 - 在类向导中,为您的分组框控件添加一个成员变量,从“Category”(类别)列表中选择“Control”(控件),然后从“Variable Type”(变量类型)列表中选择“
CGroupControl
”。(如果CGroupControl
没有出现在列表中,您可能需要删除您的类向导文件(.clw)并重新生成它。) - 要利用启用、显示和移动功能,您只需要做以上这些。
文档
该控件有一个函数,该函数会遍历其同级控件,以查看它们是否位于分组框控件的边界内。然后,这些控件会通过回调函数进行处理。包含的功能是为了处理 WM_ENABLE
、WM_SHOWWINDOW
和 WM_WINDOWPOSCHANGING
的消息,但这可以很容易地扩展以执行任何操作。确定控件属于哪个组的方法将在下面描述,随后是回调机制的描述。
迭代
为了确定控件是否属于一个组,组控件会遍历其同级控件,获取它们的位置,然后简单地测试它们是否位于分组框的边界内。关于这一点有几个选项:
- 是否包含仅部分位于组内的控件,即重叠的控件。
- 是查看所有控件,还是只查看那些制表符顺序排在分组框之后的控件。
默认情况下,控件不会包含重叠的控件,并且会查看所有同级控件。为了改变这种行为,可以使用以下两个函数:
void SetAllowOverlap(BOOL bAllowOverlap = TRUE); void SetUseTabOrder(BOOL bUseTabOrder = TRUE);
如果设置了 UseTabOrder
选项,那么组将从其第一个同级控件开始查找,并在找到第一个不在其边界内的控件时停止迭代。这样会稍微快一些,但依赖于正确设置制表符顺序。
控件操作
则回调函数签名为:
BOOL GroupControlActionFunc(CWnd*, LPARAM);
这被 typedef 为 GROUPCONTROLACTIONFUNC
。
用于遍历控件的函数是:
BOOL DoGroupControlAction(GROUPCONTROLACTIONFUNC pfnGCAF, LPARAM lParam = 0)
调用此函数,传递回调函数的地址,将遍历组的控件,并为每个控件调用回调函数,传递一个指向控件的 CWnd
指针,以及传递给 DoGroupControlAction
的 lParam
。lParam
用于将任何相关信息传递给回调函数。
例如,以下代码是用于实现组控件启用/禁用功能的 回调函数:
static BOOL GroupControlActionFunc_Enable(CWnd* pCtrl, LPARAM lParam) { if (pCtrl == NULL) return TRUE; BOOL bEnable = (BOOL)lParam; pCtrl->EnableWindow(bEnable); return TRUE; }
这是通过以下对 DoGroupControlAction
的调用来触发的:
DoGroupControlAction(GroupControlActionFunc_Enable, bEnable);
在此,lParam
仅用于指定是启用还是禁用控件。
可以通过调用 IgnoreControls()
函数并传入 TRUE
来设置组控件忽略其控件,不执行任何操作。这会使组控件像普通组控件一样工作。这在其他子控件移动所有同级控件时特别有用,例如 Peter Mares 的 CKCSideBannerWnd 横幅控件。
函数
类中的公共函数如下:
CGroupControl();
标准的空构造函数
BOOL Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID);
创建控件。这与
CButton::Create()
相同,增加了对分组框样式是否正确的检查。BOOL IsInGroup(CWnd* pCtrl, BOOL& bOverlapped);
可用于确定任何控件是否属于一个组。如果控件的任何部分位于组的边界内,则函数返回
TRUE
。如果仅控件的一部分位于组内,则bOverlapped
被设置为TRUE
。BOOL DoGroupControlAction(GROUPCONTROLACTIONFUNC pfnGCAF, LPARAM lParam = 0);
此函数可用于遍历组的控件,并对每个项执行操作。
pfnGCAF
是为每个项调用的回调函数,传递一个代表控件的CWnd
指针。lParam
是传递给回调函数的应用程序定义的 值。请注意,如果组控件设置为忽略其控件,则调用此函数不会对控件产生任何影响。void SetUseTabOrder(BOOL bUseTabOrder = TRUE);
如果
bUseTabOrder
为TRUE
,则组将围绕控件进行迭代,从组后的第一个同级控件开始,到组内最后一个控件结束。如果bUseTabOrder
为FALSE
,则组将查看所有同级控件。void SetAllowOverlap(BOOL bAllowOverlap = TRUE);
如果
bAllowOverlap
为TRUE
,则只要控件的任何部分位于组的边界内,组就会认为该控件属于该组。如果bAllowOverlap
为FALSE
,则整个控件必须位于组的边界内才属于该组。这仅在遍历控件时适用。BOOL GetUseTabOrder();
返回迭代是否使用控件制表符顺序。
BOOL GetAllowOverlap();
返回重叠控件是否被视为属于该组。
void IgnoreControls(BOOL bIgnore = TRUE);
使组像普通分组框一样工作,不对组内的控件执行操作。请注意,这不会影响
IsInGroup()
函数的行为。BOOL ControlsIgnored() const;
返回组是否设置为忽略其控件。
历史
- 版本 1.1 - 2005年2月17日
- 添加了“
IgnoreControls
”方法,允许分组框移动/调整大小等,而组内的控件不执行相同的操作,即使组控件像普通组控件一样工作。这在其他子控件移动所有同级控件时很有用,例如 Peter Mares 的 CKCSideBannerWnd 横幅控件。
- 添加了“
- 版本 1 - 2002年7月24日 - 第一个版本。