EnableGroupboxControls - 一个非 MFC 函数,用于启用或禁用组框内的所有控件






3.65/5 (9投票s)
EnableGroupboxControls 是一个函数,它仅根据控件的窗口矩形来启用或禁用组框内的所有控件。文中还解释了一种实现组框复选框的简单方法。
引言
EnableGroupboxControls 是我在几个项目中使用的函数,我希望在这些项目中启用/禁用组框内的所有控件。CodeProject 上还有其他几种解决此问题的方法 - 我在此处 列出了一个列表。然而,这些方法中没有一个包含我想要的所有内容。![]() |
可用于 MFC 或非 MFC 项目 - 由于我花了很多时间维护旧的 Windows 应用程序,所以我想要一种非常轻量级的解决方案。 |
![]() |
无需实例化类即可使用 - 这很重要,因为我必须尽量减少对现有代码的影响。 |
![]() |
无需重新编码或重新定义现有控件变量即可使用 - 同样,出于与上一点相同的原因。 |
![]() |
可容纳嵌套的组框 - 我维护的应用程序中的许多对话框并非微不足道,因为应用程序本身高度技术化。嵌套组框是处理复杂用户界面的一种方法。 |
EnableGroupboxControls API
这是 EnableGroupboxControls 函数//============================================================================= // // EnableGroupboxControls() // // Purpose: This function enables/disables all the controls that are // completely contained with a groupbox. // // Parameters: hWnd - HWND of groupbox control // bEnable - TRUE = enable controls within groupbox // // Returns: int - number of controls enabled/disabled. If zero is // returned, it means that no controls lie within the // rect of the groupbox. // int EnableGroupboxControls(HWND hWnd, BOOL bEnable) { int rc = 0; if (::IsWindow(hWnd)) { // get class name TCHAR szClassName[MAX_PATH]; szClassName[0] = _T('\0'); ::GetClassName(hWnd, szClassName, sizeof(szClassName)/sizeof(TCHAR)-2); // get window style LONG lStyle = ::GetWindowLong(hWnd, GWL_STYLE); if ((_tcsicmp(szClassName, _T("Button")) == 0) && ((lStyle & BS_GROUPBOX) == BS_GROUPBOX)) { // this is a groupbox RECT rectGroupbox; ::GetWindowRect(hWnd, &rectGroupbox); // get first child control HWND hWndChild = 0; HWND hWndParent = ::GetParent(hWnd); if (IsWindow(hWndParent)) hWndChild = ::GetWindow(hWndParent, GW_CHILD); while (hWndChild) { RECT rectChild; ::GetWindowRect(hWndChild, &rectChild); // check if child rect is entirely contained within groupbox if ((rectChild.left >= rectGroupbox.left) && (rectChild.right <= rectGroupbox.right) && (rectChild.top >= rectGroupbox.top) && (rectChild.bottom <= rectGroupbox.bottom)) { //TRACE(_T("found child window 0x%X\n"), hWndChild); ::EnableWindow(hWndChild, bEnable); rc++; } // get next child control hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT); } // if any controls were affected, invalidate the parent rect if (rc && IsWindow(hWndParent)) { ::InvalidateRect(hWndParent, NULL, FALSE); } } } return rc; }
EnableGroupboxControls 演示
EnableGroupboxControls 演示应用程序展示了如何启用/禁用组框内的控件。
void CEnableGroupboxControlsTestDlg::OnCheck1() { UpdateData(TRUE); EnableGroupboxControls(::GetDlgItem(m_hWnd, IDC_GROUPBOX_1), m_bCheck1); // enable controls within embedded groupbox OnCheck2(); } void CEnableGroupboxControlsTestDlg::OnCheck2() { UpdateData(TRUE); EnableGroupboxControls(::GetDlgItem(m_hWnd, IDC_GROUPBOX_2), m_bCheck1 && m_bCheck2); }请注意,除了上述代码中看到的之外,复选框和组框之间没有其他联系。两个组框在对话框模板中创建,其字段为空白(而不是文本)。然后创建复选框并覆盖在组框上,从而使视觉外观看起来像一个由复选框“控制”的组框。以下是演示应用程序的对话框模板,其中两个复选框/组合框对已突出显示。
只有了解技巧,才能将组框标题覆盖上复选框:组框必须在选项卡顺序中先于复选框出现。选项卡顺序是指控件在对话框模板中的出现顺序。如果组框在复选框之后,它将覆盖复选框,用户将看不到复选框。之所以这样工作,是因为对话框模板中控件的顺序也是控件在运行时创建和显示时的顺序。
您可以在 Visual Studio 中设置选项卡顺序,但对于重叠的控件,这并不完全简单。以下是 VS2005 中对话框模板的外观,其中选项卡顺序标签通过菜单命令 格式 | 选项卡顺序 可见。
当然,为了使用 EnableGroupboxControls,不一定非要在组框标题中放置复选框。标有 禁用组框 3 的按钮是如何做到这一点的示例。
如何使用
步骤 1 - 添加文件
要将 EnableGroupboxControls 集成到您的应用程序中,您首先需要将以下文件添加到您的项目中
- EnableGroupboxControls.cpp
- EnableGroupboxControls.h
在 Visual Studio 中,.cpp 文件应设置为 不使用预编译头。 否则,您会收到错误
fatal error C1010: unexpected end of file while looking for precompiled header directive
步骤 2 - 将头文件添加到您的源模块
在您要使用 EnableGroupboxControls 的模块中,包含头文件EnableGroupboxControls.h。
步骤 3 - 添加代码
当用户单击复选框(或进行某种选择)时,添加我上面显示的类似代码,以调用 EnableGroupboxControls 函数。参考文献
以下是一些讨论如何管理组框内控件的其他文章- 最简单的可检查组框类,作者:Ziming
- CGroupCheck - 与组框关联的复选框,作者:Ming Liu
- CGroupCheckBox 控件,作者:RancidCrabtree
- GroupControl,作者:Paul S. Vickery
- CGroup - 功能强大的组控件,作者:David Msika
修订历史
版本 1.0 - 2008 年 4 月 9 日
- 首次公开发布
用法
本软件已发布至公有领域。您可以随心所欲地使用它,但不得出售此源代码。如果您修改或扩展它,请考虑将新代码发布到此处供大家共享。本软件按“原样”提供,不附带任何明示或暗示的保证。对于本软件可能造成的任何损坏或业务损失,本人概不负责。