CGroupCheck - Checkbox Associated with a groupbox






4.86/5 (13 votes)
Aug 17, 2002
3 min read

310097

5134
CButton-derived control associated with a groupbox to enable/disable controls inside
Introduction
I've seen and tried several similar controls available on CodeProject and CodeGuru site. None of them meets my requirements. Some of them are too complicated and some others miss functions I need.
CGroupCheck
is a simple class derived from CButton
. A groupbox
can be associated with this button (actually a checkbox
). It has the following features:
- The
checkbox
is moved to the top left corner of thegroupbox
and resized properly. - All controls within the
groupbox
are enabled whencheckbox
is checked, and disabled whencheckbox
is unchecked. - You can optionally hide the controls inside the
groupbox
when unchecked.
How to Use It
Using the CGroupCheck
class is quite straightforward, as illustrated in the demo project.
- Create your controls on the dialog template as usual. For this control to work, you need a
checkbox
, and agroupbox
. Inside thegroupbox
, you can put any control. It doesn't matter where thecheckbox
is. Also, the tab order of thecheckbox
is unimportant. Thegroupbox
can have a caption, but it will be removed at run-time. - Create a data member of
CGroupCheck
in your dialog class. You can map this member to thecheckbox
control using DDX, or subclass thecheckbox
inOnInitDialog
message handler. - Associate the
groupbox
with thecheckbox
by calling itsSetGroupbox
function.
How Does It Work
CGroupCheck
captures checkbox
's click event and SetCheck
function to enable or disable controls inside the associated groupbox
. At its core is the function CheckGroupboxControls
.
// Enable or disable controls inside the groupbox based
// on the checkbox state. If checkbox is unchecked and
// m_bHideDisabled is set TRUE, the groupbox and all
// controls inside are hidden. For a tri-state checkbox in
// immediate state, all controls inside are just disabled.
void CGroupCheck::CheckGroupboxControls()
{
ASSERT(m_pGroupbox);
int nCheck = GetCheck();
CRect rcGroupbox;
m_pGroupbox->GetWindowRect(rcGroupbox);
// Get first child control
CWnd* pWnd = GetParent()->GetWindow(GW_CHILD);
CRect rcWnd, rcTest;
while (pWnd)
{
pWnd->GetWindowRect(rcWnd);
if (rcTest.IntersectRect(rcGroupbox, rcWnd) &&
pWnd != this && pWnd != m_pGroupbox)
{
pWnd->EnableWindow(nCheck == 1);
if (m_bHideDisabled)
pWnd->ShowWindow(nCheck ? SW_SHOW : SW_HIDE);
}
pWnd = pWnd->GetWindow(GW_HWNDNEXT);
}
if (m_bHideDisabled)
m_pGroupbox->ShowWindow(nCheck ? SW_SHOW : SW_HIDE);
}
When the checkbox
is moved to the top of the groupbox
, one problem is that the checkbox
window is normally longer than the caption. That would make the underneath groupbox
border invisible. Adjusting the checkbox
's size to fit the caption length is tedious. Also, sometimes, when checkbox
is moved on top of the groupbox
, it's actually hiding behind the groupbox
(it looks once I got this problem, changing the tab order doesn't help). All these problems are now taken care for you, when you associate the groupbox
by calling SetGroupbox
:
// Sets groupbox by Resource ID
void CGroupCheck::SetGroupbox(
UINT nGroupboxID, BOOL bHideDisabled /*= FALSE*/)
{
SetGroupbox((CButton*)GetParent()->GetDlgItem(
nGroupboxID), bHideDisabled);
}
// Sets groupbox by a pointer to that
void CGroupCheck::SetGroupbox(
CButton* pGroupbox, BOOL bHideDisabled /*= FALSE*/)
{
m_bHideDisabled = bHideDisabled;
m_pGroupbox = pGroupbox;
// Clear the groupbox text
pGroupbox->SetWindowText(_T(""));
// Sometimes the window size of the checkbox is much
// bigger than the text, let's trim it.
CString strText;
GetWindowText(strText);
// Figure out how long the text really is
CClientDC dc(this);
CFont* pOldFont = dc.SelectObject(GetFont());
CSize czText = dc.GetTextExtent(strText);
dc.SelectObject(pOldFont);
// Add some space for the checkbox and at the end
czText.cx += 25;
// Move the checkbox on top of the groupbox
CRect rc;
pGroupbox->GetWindowRect(rc);
GetParent()->ScreenToClient(rc);
SetWindowPos(pGroupbox, rc.left+10,
rc.top, czText.cx, czText.cy, 0);
// Check controls within the groupbox based
// on the check state
CheckGroupboxControls();
}
Postlude
How to Associate One Checkbox With Multiple Groupboxes?
You can create an invisible groupbox
which includes these multiple groupbox
es and associate the invisible groupbox
with the checkbox
. In this case, my code doesn't work well if the flag m_bHideDisabled
is set to true
- it will make the invisible groupbox
visible when checked. I didn't fix it because it would require another data member to remember its original state, and in particular, I don't need it at all. Of course, another limitation is that these groupbox
es must be located together to fit within that big groupbox
. If you really look for such features, you may try Pavel Sokolov's Enable/Disable a group of controls with one click, or Paul S. Vickery's GroupControl.
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.
A list of licenses authors might use can be found here.