如何将子控件放在组框中?

时间:2008-10-18 04:06:29

标签: c user-interface winapi

当我启用通用控件视觉样式支持(InitCommonControls())并且我使用除Windows经典主题之外的任何主题时,组框内的按钮显示为带方角的黑色边框。

Windows经典主题显示正常,以及关闭视觉样式时。

我使用以下代码:

group_box = CreateWindow(TEXT("BUTTON"), TEXT("BS_GROUPBOX"), 
    WS_CHILD | WS_VISIBLE | BS_GROUPBOX | WS_GROUP,
    10, 10, 200, 300,
    hwnd, NULL, hInstance, 0);

push_button = CreateWindow(TEXT("BUTTON"), TEXT("BS_PUSHBUTTON"),
    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
    40, 40, 100, 22,
    group_box, NULL, hInstance, 0);

编辑:单选按钮也会出现问题

编辑:我没有使用任何对话框/资源,只有CreateWindow / Ex。

我在Visual C ++ 2008 Express SP1下编译,使用通用的manifest文件

Screenshot http://img.ispankcode.com/black_border_issue.png

4 个答案:

答案 0 :(得分:4)

问题是将groupbox作为控件的父级。 Groupboxes不应该有任何子节点并且使用它们作为父节点会导致各种错误(包括绘画,键盘导航和消息传播)。只需将按钮的CreateWindow调用中的父项从 group_box 更改为 hwnd (即对话框)。

我猜你使用了groupbox作为父级,以便轻松地将其他控件放在其中。正确的方法是获取组框客户区的位置并将其映射到对话框的客户区。放置在生成的RECT中的所有内容都将显示在组框内。由于groupbox实际上没有客户区,因此可以使用以下内容进行计算:

// Calculate the client area of a dialog that corresponds to the perceived
// client area of a groupbox control. An extra padding in dialog units can
// be specified (preferably in multiples of 4).
//
RECT getClientAreaInGroupBox(HWND dlg, int id, int padding = 0) {
    HWND group = GetDlgItem(dlg, id);
    RECT rc;
    GetWindowRect(group, &rc);
    MapWindowPoints(0, dlg, (POINT*)&rc, 2);

    // Note that the top DUs should be 9 to completely avoid overlapping the
    // groupbox label, but 8 is used instead for better alignment on a 4x4
    // design grid.
    RECT border = { 4, 8, 4, 4 };
    OffsetRect(&border, padding, padding);
    MapDialogRect(dlg, &border);

    rc.left += border.left;
    rc.right -= border.right;
    rc.top += border.top;
    rc.bottom -= border.bottom;
    return rc;
}

请注意,这同样适用于Tab控件。它们也不是为父母设计的,也会表现出类似的行为。

答案 1 :(得分:1)

这里只是一个猜测,但看起来你继承了主题的静态边缘或客户端边缘样式。我从资源编辑器创建了大部分对话框并在那里设置了这些属性。

在您的情况下,您可以使用CreateWindowEx替换CreateWindow来设置这些扩展样式,这些样式可能在CreateWindow中默认。具体来看WS_EX_STATICEDGE, WS_EX_WINDOWEDGE and WS_EX_CLIENTEDGE

编辑:我假设这没有发生,因为你的按钮是对话框中的默认控件,这也会产生黑边。

答案 2 :(得分:0)

显然,组框不是用于分组控件(是父级hwnd)

因此,为了摆脱黑色边框/绘画问题,我必须子类化组框并实现WM_PAINT和WM_PRINTCLIENT

答案 3 :(得分:-2)

啊,是黑色背景,带有单选按钮和组合框。虽然我不确定这是否适用于VC ++ 2008,但是当天的VB6主题应用程序的解决方案是首先将无线电控件放在PictureBox(真正的通用容器)上,然后将其添加到组合框。

值得一试!