65.9K
CodeProject 正在变化。 阅读更多。
Home

CGroupCheck - 与分组框关联的复选框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (13投票s)

2002年8月17日

3分钟阅读

viewsIcon

311255

downloadIcon

5175

与分组框关联的 CButton 派生控件,用于启用/禁用内部控件

Sample Image - GroupCheck.gif

引言

我见过并尝试过 CodeProject 和 CodeGuru 网站上提供的几个类似的控件。它们都不符合我的要求。有些太复杂,有些缺少我需要的功能。

CGroupCheck 是一个从 CButton 派生的简单类。一个 groupbox 可以与此按钮(实际上是一个 checkbox)关联。它具有以下功能

  1. checkbox 被移动到 groupbox 的左上角并正确调整大小。
  2. checkbox 被选中时,groupbox 内的所有控件都被启用;当 checkbox 未被选中时,它们被禁用。
  3. 您可以选择在未选中时隐藏 groupbox 内的控件。

如何使用它

使用 CGroupCheck 类非常简单,如演示项目所示。

  • 像往常一样在对话框模板上创建控件。为了使此控件正常工作,您需要一个 checkbox 和一个 groupbox。在 groupbox 内部,您可以放置任何控件。checkbox 的位置无关紧要。此外,checkbox 的 Tab 顺序并不重要。groupbox 可以有一个标题,但它将在运行时被删除。
  • 在对话框类中创建一个 CGroupCheck 的数据成员。您可以使用 DDX 将此成员映射到 checkbox 控件,或者在 OnInitDialog 消息处理程序中子类化 checkbox
  • 通过调用其 SetGroupbox 函数将 groupboxcheckbox 关联。

它是如何工作的

CGroupCheck 捕获 checkbox 的 click 事件和 SetCheck 函数,以启用或禁用关联的 groupbox 内的控件。其核心是函数 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);
}

checkbox 移动到 groupbox 的顶部时,一个问题是 checkbox 窗口通常比标题长。这将使底部的 groupbox 边框不可见。调整 checkbox 的大小以适应标题长度非常繁琐。此外,有时,当 checkbox 移动到 groupbox 的顶部时,它实际上隐藏在 groupbox 后面(我曾经遇到过这个问题,改变 Tab 顺序没有帮助)。当您通过调用 SetGroupbox 关联 groupbox 时,所有这些问题现在都为您解决了

// 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();
}

结语

如何将一个复选框与多个分组框关联?

您可以创建一个包含这些多个 groupbox 的不可见 groupbox,并将不可见 groupboxcheckbox 关联。在这种情况下,如果标志 m_bHideDisabled 设置为 true,我的代码不能很好地工作 - 它会在选中时使不可见的 groupbox 可见。我没有修复它,因为它需要另一个数据成员来记住它的原始状态,特别是,我根本不需要它。当然,另一个限制是这些 groupbox 必须位于一起才能适合那个大的 groupbox。如果您真的在寻找这样的功能,您可以尝试 Pavel Sokolov 的 用一次点击启用/禁用一组控件,或 Paul S. Vickery 的 GroupControl

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.