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






4.86/5 (13投票s)
2002年8月17日
3分钟阅读

311255

5175
与分组框关联的 CButton 派生控件,用于启用/禁用内部控件
引言
我见过并尝试过 CodeProject 和 CodeGuru 网站上提供的几个类似的控件。它们都不符合我的要求。有些太复杂,有些缺少我需要的功能。
CGroupCheck
是一个从 CButton
派生的简单类。一个 groupbox
可以与此按钮(实际上是一个 checkbox
)关联。它具有以下功能
checkbox
被移动到groupbox
的左上角并正确调整大小。- 当
checkbox
被选中时,groupbox
内的所有控件都被启用;当checkbox
未被选中时,它们被禁用。 - 您可以选择在未选中时隐藏
groupbox
内的控件。
如何使用它
使用 CGroupCheck
类非常简单,如演示项目所示。
- 像往常一样在对话框模板上创建控件。为了使此控件正常工作,您需要一个
checkbox
和一个groupbox
。在groupbox
内部,您可以放置任何控件。checkbox
的位置无关紧要。此外,checkbox
的 Tab 顺序并不重要。groupbox
可以有一个标题,但它将在运行时被删除。 - 在对话框类中创建一个
CGroupCheck
的数据成员。您可以使用 DDX 将此成员映射到checkbox
控件,或者在OnInitDialog
消息处理程序中子类化checkbox
。 - 通过调用其
SetGroupbox
函数将groupbox
与checkbox
关联。
它是如何工作的
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
,并将不可见 groupbox
与 checkbox
关联。在这种情况下,如果标志 m_bHideDisabled
设置为 true
,我的代码不能很好地工作 - 它会在选中时使不可见的 groupbox
可见。我没有修复它,因为它需要另一个数据成员来记住它的原始状态,特别是,我根本不需要它。当然,另一个限制是这些 groupbox
必须位于一起才能适合那个大的 groupbox
。如果您真的在寻找这样的功能,您可以尝试 Pavel Sokolov 的 用一次点击启用/禁用一组控件,或 Paul S. Vickery 的 GroupControl。
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。