Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / MFC

CGroupCheck - Checkbox Associated with a groupbox

Rate me:
Please Sign up or sign in to vote.
4.86/5 (14 votes)
16 Aug 20023 min read 308.1K   5.1K   68   17
CButton-derived control associated with a groupbox to enable/disable controls inside

Sample Image - GroupCheck.gif

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:

  1. The checkbox is moved to the top left corner of the groupbox and resized properly.
  2. All controls within the groupbox are enabled when checkbox is checked, and disabled when checkbox is unchecked.
  3. 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 a groupbox. Inside the groupbox, you can put any control. It doesn't matter where the checkbox is. Also, the tab order of the checkbox is unimportant. The groupbox 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 the checkbox control using DDX, or subclass the checkbox in OnInitDialog message handler.
  • Associate the groupbox with the checkbox by calling its SetGroupbox 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.

C++
// 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:

C++
// 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 groupboxes 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 groupboxes 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.


Written By
Web Developer
Germany Germany
to be created...

Comments and Discussions

 
PraiseThank you ! it's just what i need. Pin
xl_fire10-Dec-15 19:20
xl_fire10-Dec-15 19:20 
QuestionThanks Pin
Member 81095601-Dec-11 22:25
Member 81095601-Dec-11 22:25 
Generalcheckbox hiding behind the groupbox Pin
Rauf Abbasi26-Feb-09 4:34
Rauf Abbasi26-Feb-09 4:34 
GeneralRe: checkbox hiding behind the groupbox Pin
Matthew J. Bobowski24-Jan-18 14:08
Matthew J. Bobowski24-Jan-18 14:08 
QuestionHow can i do same thing in c# or VB .Net Pin
MichaelNu3-Jun-07 1:00
MichaelNu3-Jun-07 1:00 
GeneralVery good Pin
Norbertbetko26-Jul-06 23:49
Norbertbetko26-Jul-06 23:49 
GeneralA small problem Pin
Huang, Xiong14-May-05 6:52
Huang, Xiong14-May-05 6:52 
GeneralVery handy. Thank you! Pin
nedelman16-Jul-03 11:56
nedelman16-Jul-03 11:56 
QuestionHow to create a check box of bigger size? Pin
Dhirendra1-May-03 3:52
Dhirendra1-May-03 3:52 
AnswerRe: How to create a check box of bigger size? Pin
Ming Liu13-Aug-04 8:30
Ming Liu13-Aug-04 8:30 
GeneralRe: How to create a check box of bigger size? Pin
ystein17-Jan-07 6:31
ystein17-Jan-07 6:31 
I checked here to find out how I could make the box itself bigger, not the frame with the text next to and around the checkbox.
Is that possible?

Øystein
Generalrepainting Pin
Anonymous17-Sep-02 19:45
Anonymous17-Sep-02 19:45 
GeneralRe: repainting Pin
Ming Liu19-Sep-02 14:30
Ming Liu19-Sep-02 14:30 
GeneralNice Pin
johnston28-Aug-02 9:46
johnston28-Aug-02 9:46 
Generaldestructor! Pin
a97alika18-Aug-02 10:20
a97alika18-Aug-02 10:20 
GeneralRe: destructor! Pin
Ming Liu19-Aug-02 3:50
Ming Liu19-Aug-02 3:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.