Как разместить субэлементы управления внутри группового поля?

Когда я включаю поддержку визуального стиля общего элемента управления (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 с общим файлом манифест

Скриншот http://img.ispankcode.com/black_border_issue.png

Появляется ли черная рамка вокруг всех кнопок или только на изображении, которое вы предоставили?

RobS 18.10.2008 08:50

Все кнопки. Если я использую классическую тему Windows, они выглядят как обычно.

Bob Jones 18.10.2008 08:59

Как выглядит вызов CreateWindow для самого родительского диалога? Просто интересно, происходит ли какое-то наследование.

RobS 18.10.2008 13:13

hwnd = CreateWindow (appName, TEXT («Скелет окна»), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 435,360, NULL‌, NULL, hInstance, 0);

Bob Jones 18.10.2008 19:41

Хм. Это происходит, если кнопки тоже находятся за пределами группового поля?

RobS 19.10.2008 17:20

Нет, только когда они находятся внутри группового поля, другими словами, когда я использую group_box в качестве родительского hwnd.

Bob Jones 20.10.2008 02:17

Я попробую повторить завтра вечером и посмотрю, смогу ли я найти решение

RobS 20.10.2008 16:52

Проблема заключается в использовании группового ящика в качестве родительского. Не стоит этого делать;) Я тестировал и получаю такие же черные границы. См. Мой ответ для более подробной информации.

efotinis 17.11.2008 22:34
WS_CLIBSIBLINGS на Group Box тоже стоит попробовать.
Laurie Stearn 10.06.2020 18:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
9
7 157
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Просто предположение, но похоже, что вы наследуете стиль Static Edge или Client Edge от своей темы. Я создаю большинство своих диалогов из редактора ресурсов и устанавливаю там эти свойства.

В вашем случае вы можете заменить CreateWindow на CreateWindowEx, чтобы установить эти расширенные стили, которые, вероятно, используются по умолчанию в CreateWindow. Конкретно проверьте WS_EX_STATICEDGE, WS_EX_WINDOWEDGE and WS_EX_CLIENTEDGE

Обновлено: я предполагаю, что этого не происходит, потому что кнопка является элементом управления по умолчанию в диалоговом окне, что также дает черный край.

По-видимому, групповые поля не предназначены для группировки элементов управления (быть родительским hwnd)

Итак, чтобы избавиться от черных границ / проблем с рисованием, мне пришлось бы создать подкласс группового блока и реализовать WM_PAINT и WM_PRINTCLIENT

Ах да, черный фон с переключателями и групповыми блоками. Хотя я не уверен, будет ли это работать для VC++ 2008, но в те времена решение для тематических приложений VB6 состояло в том, чтобы сначала поместить элементы управления радио в PictureBox (на самом деле общий контейнер), а затем добавить это в групповое поле.

Стоит попробовать!

Ответ принят как подходящий

Проблема заключается в том, что групповой ящик является родительским элементом управления. У групповых ящиков не должно быть дочерних элементов, и использование их в качестве родителей вызовет всевозможные ошибки (включая рисование, навигацию с клавиатуры и распространение сообщений). Просто измените родительский элемент в вызове кнопок CreateWindow с group_box на hwnd (т.е. диалог).

Я предполагаю, что вы использовали групповой ящик в качестве родителя, чтобы легко разместить в нем другие элементы управления. Правильный способ сделать это - получить позицию клиентской области группового окна и сопоставить ее с клиентской областью диалога. Все, что помещено в результирующий RECT, появится внутри группового окна. Поскольку у групповых ящиков на самом деле нет клиентской области, ее можно рассчитать примерно так:

// 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. Они тоже не созданы для того, чтобы быть родителями, и будут демонстрировать подобное поведение.

Как именно вы "получаете позицию клиентской области группового ящика"? GetClientRect дает область, включая границы и заголовок, что не позволяет размещать без рисования поверх чего-либо.

nwp 23.10.2014 21:10

@nwp, хороший вопрос. Мне не удалось найти исходную реализацию, но я добавил в свой ответ возможное решение. По сути, это взлом с использованием диалоговых модулей.

efotinis 02.11.2014 12:17

Другие вопросы по теме