Цвет фона статического элемента управления с C++

Я создаю базовый графический интерфейс с помощью Windows API и столкнулся с проблемой. Он начинается с главного окна, которое открывается с пользовательским цветом фона, который я установил (RGB(230,230,230)). Затем он отображает текст в верхнем левом углу со статическим элементом управления.

settingstext = CreateWindow("STATIC",
                             "SETTINGS",
                             SS_LEFT | WS_CHILD,
                             12,
                             20,
                             100,
                             20,
                             hwnd,
                             NULL,
                             proginstance,
                             NULL);
ShowWindow(settingstext, 1);

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

Мой вопрос в том, как мне это сделать? В настоящее время я использую метод, описанный ниже, и он работает, но я хотел знать, есть ли способ как-то навсегда установить цвет фона сразу после функции CreateWindow для статического элемента управления без изменения системных цветов, и просто применить его к этому управление, а не все, что отправляет сообщение WM_CTLCOLORSTATIC. Я экспериментировал с использованием функции GetDC и функции SetBkColor вне цикла сообщений, но ничего не работает.

    case WM_CTLCOLORSTATIC:
    {
    HDC hdcStatic = (HDC) wParam;
    SetTextColor(hdcStatic, RGB(0,0,0));
    SetBkColor(hdcStatic, RGB(230,230,230));
    return (INT_PTR)CreateSolidBrush(RGB(230,230,230));
    }

Я хочу сделать это, потому что...

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

Я был бы очень благодарен за любую помощь, которая может быть оказана, по крайней мере, указав мне правильное направление, спасибо.


person contrapsych    schedule 21.12.2010    source источник
comment
Вы можете ограничить действие кода WM_CTLCOLORSTATIC только вашим статическим элементом управления, проверив, что (HWND)lParam == settingstext. Проблема с вашим примером заключается в том, что все созданные вами кисти никогда не будут удалены.   -  person Brian Nixon    schedule 21.12.2010


Ответы (3)


Для статических текстовых элементов управления нет постоянного способа установить цвет текста или их фон. Даже если вы хотите применить изменения к одному статическому элементу управления; вам все равно придется обрабатывать сообщение уведомления WM_CTLCOLORSTATIC в родительской dlgproc как раз тогда, когда элемент управления вот-вот будет нарисован.

Это связано с тем, что DefWindowProc перезаписывает ваши изменения в контексте устройства каждый раз, когда оно обрабатывает WM_CTLCOLORSTATIC, как указано в MSDN:

По умолчанию функция DefWindowProc выбирает системные цвета по умолчанию для статического элемента управления.

static HBRUSH hBrush = CreateSolidBrush(RGB(230,230,230));

case WM_CTLCOLORSTATIC:
{
    if (settingstext == (HWND)lParam)

              //OR if the handle is unavailable to you, get ctrl ID

    DWORD CtrlID = GetDlgCtrlID((HWND)lParam); //Window Control ID
    if (CtrlID == IDC_STATIC1) //If desired control
    {
       HDC hdcStatic = (HDC) wParam;
       SetTextColor(hdcStatic, RGB(0,0,0));
       SetBkColor(hdcStatic, RGB(230,230,230));
       return (INT_PTR)hBrush;
    }
}

Если вы хотите сделать фон элемента управления прозрачным поверх родительского диалога, вы можете использовать SetBkMode(hdcStatic, TRANSPARENT).

person cpx    schedule 21.12.2010
comment
Можете объяснить, зачем нужно создавать hBrush для фона, если вы уже звонили SetBkColor? А в случае прозрачного фона нужна еще и прозрачная кисть? - person Ameen; 05.12.2015

Я думаю, что есть постоянный способ сделать это.

Сразу после создания метки используйте функцию GetDC() для получения контекста устройства. Затем используйте:

SetTextColor(hdcStatic, RGB(0,0,0));
SetBkColor(hdcStatic, RGB(230,230,230)); // Code Copied from the above answer by cpx.

Так и должно быть.

person NoMadCap    schedule 08.02.2015
comment
Это не работает, потому что DefWindowProc будет сбрасывать эти изменения в контекст устройства каждый раз, когда он обрабатывает сообщение WM_CTLCOLORSTATIC для элемента управления. MSDN: Автор default, функция DefWindowProc выбирает системные цвета по умолчанию для статического элемента управления. - person whY; 21.03.2018

Рассматривали ли вы создание подкласса статического окна и рисование владельцем?

person Jonathan Wood    schedule 21.12.2010
comment
Я понятия не имею, что это такое, поэтому я проведу небольшое исследование по подклассам. - person contrapsych; 21.12.2010
comment
По сути, это означает, что у вас есть сообщения, отправленные статическому элементу управления, чтобы вместо этого перейти к вашему коду (не забудьте передать те, которые вы не обрабатываете, исходному обработчику). Если вы обрабатываете сообщения о стирании фона и рисовании, то вы можете отображать в окне все, что захотите. - person Jonathan Wood; 21.12.2010
comment
Так что это произойдет только с этим единственным элементом управления, есть ли способ уменьшить количество функций в пользовательской процедуре, которую я бы сделал для этого элемента управления. В основном то, что я имею в виду со всем не очень большим количеством функций в процедуре, заключается в том, что кажется, что это замедлит работу приложения, которое будет выполнять эти функции каждый раз, когда оно должно перерисовывать, или это не так уж важно? - person contrapsych; 21.12.2010
comment
Это не будет медленнее, потому что ваши процедуры рисования заменят текущие (они все равно будут рисоваться). Кроме того, вам не нужно писать процедуры рисования для каждого элемента управления, который вы подклассируете. Вы можете создавать подклассы для нескольких окон с одним и тем же WndProc. Я все время это делаю. Тем не менее, это может быть излишним для того, что вам нужно. Я не совсем уверен. - person Jonathan Wood; 21.12.2010