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

EnableGroupboxControls - 一个非 MFC 函数,用于启用或禁用组框内的所有控件

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.65/5 (9投票s)

2008 年 4 月 9 日

CPOL

4分钟阅读

viewsIcon

83632

downloadIcon

1182

EnableGroupboxControls 是一个函数,它仅根据控件的窗口矩形来启用或禁用组框内的所有控件。文中还解释了一种实现组框复选框的简单方法。

引言

EnableGroupboxControls 是我在几个项目中使用的函数,我希望在这些项目中启用/禁用组框内的所有控件。CodeProject 上还有其他几种解决此问题的方法 - 我在此处 列出了一个列表。然而,这些方法中没有一个包含我想要的所有内容。
screenshot 可用于 MFC 或非 MFC 项目 - 由于我花了很多时间维护旧的 Windows 应用程序,所以我想要一种非常轻量级的解决方案。
screenshot 无需实例化类即可使用 - 这很重要,因为我必须尽量减少对现有代码的影响。
screenshot 无需重新编码或重新定义现有控件变量即可使用 - 同样,出于与上一点相同的原因。
screenshot 可容纳嵌套的组框 - 我维护的应用程序中的许多对话框并非微不足道,因为应用程序本身高度技术化。嵌套组框是处理复杂用户界面的一种方法。

EnableGroupboxControls API

这是 EnableGroupboxControls 函数
//=============================================================================
//
// 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 演示

EnableGroupboxControls 演示应用程序展示了如何启用/禁用组框内的控件。

screenshot

当组框 1 的复选框被取消选中时,组框 1 和组框 2 内的所有控件都将被禁用。

screenshot

这是管理这些嵌套组框的代码
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);
}
请注意,除了上述代码中看到的之外,复选框和组框之间没有其他联系。两个组框在对话框模板中创建,其字段为空白(而不是文本)。然后创建复选框并覆盖在组框上,从而使视觉外观看起来像一个由复选框“控制”的组框。以下是演示应用程序的对话框模板,其中两个复选框/组合框对已突出显示。

screenshot

只有了解技巧,才能将组框标题覆盖上复选框:组框必须在选项卡顺序先于复选框出现。选项卡顺序是指控件在对话框模板中的出现顺序。如果组框在复选框之后,它将覆盖复选框,用户将看不到复选框。之所以这样工作,是因为对话框模板中控件的顺序也是控件在运行时创建和显示时的顺序。
您可以在 Visual Studio 中设置选项卡顺序,但对于重叠的控件,这并不完全简单。以下是 VS2005 中对话框模板的外观,其中选项卡顺序标签通过菜单命令 格式 | 选项卡顺序 可见。

screenshot

红色轮廓中的两个组框标题是被复选框覆盖的标题。由于 1 和 2、8 和 9 的选项卡顺序标签显示在彼此之上,因此很难在 VS IDE 中设置选项卡顺序。但是,一如既往,有一个技巧:暂时将复选框移到组框上方或下方,然后编辑选项卡顺序。完成后,将复选框移回原位。

当然,为了使用 EnableGroupboxControls,不一定非要在组框标题中放置复选框。标有 禁用组框 3 的按钮是如何做到这一点的示例。

如何使用

步骤 1 - 添加文件

要将 EnableGroupboxControls 集成到您的应用程序中,您首先需要将以下文件添加到您的项目中

  • EnableGroupboxControls.cpp
  • EnableGroupboxControls.h

在 Visual Studio 中,.cpp 文件应设置为 不使用预编译头。 否则,您会收到错误

    fatal error C1010: unexpected end of file while looking for precompiled header directive

步骤 2 - 将头文件添加到您的源模块

在您要使用 EnableGroupboxControls 的模块中,包含头文件EnableGroupboxControls.h

步骤 3 - 添加代码

当用户单击复选框(或进行某种选择)时,添加我上面显示的类似代码,以调用 EnableGroupboxControls 函数。

参考文献

以下是一些讨论如何管理组框内控件的其他文章

修订历史

版本 1.0 - 2008 年 4 月 9 日

  • 首次公开发布

用法

本软件已发布至公有领域。您可以随心所欲地使用它,但不得出售此源代码。如果您修改或扩展它,请考虑将新代码发布到此处供大家共享。本软件按“原样”提供,不附带任何明示或暗示的保证。对于本软件可能造成的任何损坏或业务损失,本人概不负责。

© . All rights reserved.