C++ 如何设置多个单选按钮组以实现正确的选项卡顺序和键盘交互(WIN32)?

C++ 如何设置多个单选按钮组以实现正确的选项卡顺序和键盘交互(WIN32)?,c++,winapi,window,radio-button,win32gui,C++,Winapi,Window,Radio Button,Win32gui,首先,这不是MFC。 以下是我一直在使用的GUI的裁剪版本: 如您所见,我已(尝试)使用以下代码创建了两个不同的组:图标组和按钮组: index->hAddT.hwndIndex[2] = CreateWindowEx(NULL,L"BUTTON",L"Icon",WS_CHILD | WS_VISIBLE | BS_GROUPBOX, 200,135,120,170,WINDOWHANDLE,(HMENU)IDC_RADIOGROUP,(HINSTANCE)GetWin

首先,这不是MFC。
以下是我一直在使用的GUI的裁剪版本:

如您所见,我已(尝试)使用以下代码创建了两个不同的组:图标组和按钮组:

    index->hAddT.hwndIndex[2] = CreateWindowEx(NULL,L"BUTTON",L"Icon",WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
    200,135,120,170,WINDOWHANDLE,(HMENU)IDC_RADIOGROUP,(HINSTANCE)GetWindowLong(WINDOWHANDLE,GWL_HINSTANCE),NULL);
我的问题是,你可能会看到,窗口只有一个单选按钮。这意味着用户不可能从图标组和按钮组中分别选择一个单选按钮。我已将每个单选按钮初始化为:

    index->hAddT.hwndIndex[3] = CreateWindowEx(NULL,L"BUTTON",L"Information",WS_CHILD | BS_AUTORADIOBUTTON | WS_VISIBLE,
    205,155,100,20,WINDOWHANDLE,(HMENU)IDC_RADIO1,(HINSTANCE)GetWindowLong(WINDOWHANDLE,GWL_HINSTANCE),NULL);       
我想,不知何故,有“图标”组单选按钮从“按钮”组单选按钮分开,如果这是有意义的,因此将有一个单选按钮可供每组。 这将如何可能,它会要求我做一个新的窗口和一个新的回调过程只是有一个额外的单选按钮。必须有另一种方法对子项进行分组,就像这样

这个链接对我没有任何用处


我身边有Charles Petzold为Windows第五版编写的程序作为参考,他在“组框”一节中指出“组框通常用于封装其他按钮控件”,但没有这方面的真实示例。

与流行观点相反,您不需要组框控件或任何其他此类外部“容器”(无论如何,groupbox不是,它只是一个按钮工件)。以下描述了如何使用分组框的要求来实现这一点。如果您想要一个在功能上有助于此处所述布局的分组框,请转到此答案的编辑部分,在这里我将解释如何实现OP的特定愿望

自动单选按钮“banks”通过使用两个关键窗口样式属性来工作,WS\u GROUPWS\u TABSTOP。为您的两个“banks”(我亲切地称之为Bank1和Bank2)执行以下操作:

  • 气缸组1:第一个单选按钮应具有控件样式中的两个WS|u GROUP | WS|u TABSTOP。其余单选按钮应具有这两个按钮中的任何一个,并且必须是同级顺序(这意味着在对话框脚本中,它们立即相互跟随;在动态创建中,它们是按顺序创建的)

  • Bank1中最后一个单选按钮后的第一个子控件应至少具有WS_GROUP样式,如果是tab stopped控件,则WS_GROUP | WS_TABSTOP

  • 第2列:第一个单选按钮应具有控件样式中的两个WS|u GROUP | WS|u TABSTOP。其余单选按钮应不具有这两个单选按钮中的任何一个,并且必须是同级顺序(这意味着在对话框脚本中,它们立即相互跟随;在动态创建中,它们是按顺序创建的)

  • Bank2中最后一个单选按钮后的第一个子控件应至少具有WS_GROUP样式,如果是tab stopped控件,则WS_GROUP | WS_TABSTOP

  • 类似于上面的布局允许您“tab”到单选按钮组,并使用箭头键切换选择。然后再次“tab”离开该组并前往下一个制表位。请记住,当您点击tab(或Shift tab之前)时,对话框管理器将始终移动到下一个WS_TABTOP子控件。如果跳转到的控件是自动类型,则所选控件将是最新WS_组中的“选定”控件

    如果有帮助的话,抓起一个草图板,在纸上画出来,在制表位上粘贴一个“T”,在组属性上粘贴一个“G”,如上所述。一旦可视化,可能会更清晰。查看对话框资源脚本,了解它们是如何协同工作的,以获得更多信息

    注意:如果您想在这些控件周围使用组框,则可以使用。对话框管理器的工作方式是根据标记为WS_group的最后一个控件将控件与组相关联,之后具有WS_TABSTOP的第一个控件被视为该组的选项卡跳转点。首先插入一个Groupbox(不能是TABSTOP)然后是第一个单选按钮上带有WS_TABSTOP的单选按钮控件(这次没有WS_组),也会起作用。我通常发现,在不依赖GroupBox的情况下,只排列单选按钮更容易

    编辑一张图片能说出千言万语

    对于您的图片,我可能会按照以下顺序创建以下子对象:

  • “图标”组框,包括WS_组样式
  • “信息”自动单选按钮,包括WS_TABSTOP
  • 所有其他“图标”组单选按钮。不包括WS_TABSTOP或WS_group
  • “按钮”组框,包括WS_组样式。这将关闭当前控制组并启动下一个控制组
  • “AbortretryIgnore”自动单选按钮,包括WS_TABSTOP
  • 所有其他“按钮”组单选按钮。不包括WS_TABSTOP或WS_group
  • “按钮”单选按钮后的下一个控件必须包括WS_组。这将关闭当前控件组并启动下一个控件组

  • 显然,所有其他子控件样式、可见性等也需要正确使用,当然子控件都应该具有唯一的ID。我假设您已经涵盖了其余部分。

    注意,这也适用于一组复选框,这是一个有效的用例

    注意:如果第一个单选按钮可能被禁用(例如,由于运行时条件),则必须使第一个启用的单选按钮具有WS_TABSTOP样式。以下几行代码确保了这一点:

        // Set WS_TABSTOP to the group's first enabled item
        for (HWND hwnd = GetDlgItem(IDC_FIRSTITEM) /*the first*/; hwnd != NULL && !::IsWindowEnabled(hwnd); hwnd = ::GetWindow(hwnd, GW_HWNDNEXT))
        {
            if ((GetWindowLong(hwnd, GWL_STYLE) & WS_GROUP) != 0)
                hwnd = NULL;
        }
        if (hwnd != NULL)
            ModifyStyle(hwnd, 0, WS_TABSTOP, 0);
    

    如果您可以指向描述这一点的MSDN文档,您将获得额外的积分。@Thomas可以简单地找到描述WS_GROUP如何工作的文字,但MS的“更好”(我不严格地使用该术语)描述是。至少后者提供了“箭头键”很抱歉我也错过了,这可能是最好的。整个文档中有大量关于有效对话编程的信息。