EnableGroupboxControls - a non-MFC function to enable or disable all the controls within a groupbox
Introduction
EnableGroupboxControls is a function I have used in several projects, where I wanted to enable/disable all the controls within a groupbox. There are several other solutions to this problem here on CodeProject - I have included a list here. None of these, however, had everything I was looking for:![]() |
Able to be used in MFC or non-MFC project - since I spend a lot of time maintaining older Windows applications, I wanted a very lightweight solution. |
![]() |
Able to be used without instantiating class - this was important, because I necessarily have to minimize the impact on existing code. |
![]() |
Able to be used without recoding or redefining existing control variables - again, for same reasons as previous point. |
![]() |
Able to accommodate nested groupboxes - many of the dialogs in apps I maintain are non-trivial, because the apps themselves are highly technical. Nesting groupboxes is one way of coping with complex user interfaces. |
EnableGroupboxControls API
Here is the EnableGroupboxControls function:
//============================================================================= // // 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 Demo
The EnableGroupboxControls demo app shows how controls inside a groupbox may be enabled/disabled:
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); }Note that there is no linkage between the checkboxes and the groupboxes except what you see in the above code. The two groupboxes are created in the dialog template with a field of spaces (instead of text). Then checkboxes are created and overlaid on the groupbox, so that the visual appearance is that of a groupbox "controlled" by a checkbox. Here is dialog template for demo app, with the two checkbox/combobox pairs highlighted:
Of course, it is not necessary to have checkbox in groupbox header, in order to make use of EnableGroupboxControls. The button labelled Disable Groupbox 3 is an example of how to do this.
How to use
Step 1 - Add Files
To integrate EnableGroupboxControls into your app, you first need to add following files to your project:
- EnableGroupboxControls.cpp
- EnableGroupboxControls.h
The .cpp file should be set to Not using precompiled header in Visual Studio. Otherwise, you will get error
fatal error C1010: unexpected end of file while looking for precompiled header directive
Step 2 - Add Header File to Your Source Module
In the module where you want to use EnableGroupboxControls, include header file EnableGroupboxControls.h .
Step 3 - Add Code
When user clicks a checkbox (or makes some kind of selection). add code like I have shown above, to call EnableGroupboxControls function.References
Here are some other articles that discuss managing controls within a groupbox:- Simplest Checkable Groupbox Class by Ziming
- CGroupCheck - Checkbox associated with a groupbox by Ming Liu
- CGroupCheckBox control by RancidCrabtree
- GroupControl by Paul S. Vickery
- CGroup - A Powerful Group Control by David Msika
Revision History
Version 1.0 - 2008 April 9
- Initial public release
Usage
This software is released into the public domain. You are free to use it in any way you like, except that you may not sell this source code. If you modify it or extend it, please to consider posting new code here for everyone to share. This software is provided "as is" with no expressed or implied warranty. I accept no liability for any damage or loss of business that this software may cause.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步