Как изменить цвет кнопки?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 16.10.19 20:39
Оценка:
Сегодня утром приспичило сделать изменение цвета [фона] верхней поверхности кнопки (обычный PUSHBUTTON). Ничего больше менять не нужно — задача вроде бы примитивная донельзя. Однако, сейчас уже поздний вечер, но я в этом вопросе практически не продвинулся, зато успел изрядно охренеть.

Первой мыслью было использовать WM_CTLCOLORBTN. Однако документация утверждает (и это так и есть), что для стилей BS_PUSHBUTTON, BS_DEFPUSHBUTTON и BS_PUSHLIKE возвращаемая кисть игнорируется. Тогда для чего это сообщение шлется кнопкам с этими стилями? Какой в нем может быть практический смысл?

Видел в сети советы использовать WM_CTLCOLORSTATIC, но оно в диалог не присылается.

Следующая идея — WM_NOTIFY/NM_CUSTOMDRAW, которые для обычных кнопок поддерживаются в comctl32.dll, начиная с шестой версии. У меня версия 6.16 (Win7), все сообщения приходят, но никакой реакции на выбор кисти или карандаша, а также на SetBkColor/SetTextColor не вижу. Вставил все это и в PreErase, и в PrePaint — без толку.

Здесь предлагают в обработчике CDDS_PREERASE вызывать FillRect и возвращать CDRF_DODEFAULT, но это гарантированно не работает, поскольку стандартный обработчик тут же перезаливает область. Если вызвать FillRect по CDDS_PREPAINT, то стандартный обработчик затем рисует поверх залитого прямоугольника текст со стандартным фоном, невзирая на вызов SetBkColor.

Я, честно говоря, в полном ауте от того, что столь примитивная задача требует таких изощренных плясок. Что еще остается делать? Можно рисовать самому через WM_DRAWITEM, но это ж из пушки по воробьям. Сабклассить — тоже и громоздко, и грязно. Вызывать на время отрисовки SetSysColors — будут дергаться другие окна, а им это ни к чему?

Все действительно настолько плохо, или я где-то чего не догоняю?
кнопка button pushbutton nm_customdraw цвет фон
Re: Как изменить цвет кнопки?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 16.10.19 21:37
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Все действительно настолько плохо, или я где-то чего не догоняю?


Давно-давно, когда операционки были маленькими, процессоры — 32-битными, а памяти хватало не только на запуск браузера, заинтересовался я, как можно сделать кнопку с картинкой при включённых стилях WinXP. MFC-шный CButton::SetIcon (вроде бы, опирается на BM_SETIMAGE) картиночку-то добавлял, но саму кнопку превращал в прямоугольную классическую, что выглядело, мягко говоря, неуместно. В итоге мне тогда удалось нагуглить лишь один рабочий вариант, который наследовался от класса CButton, переопределял OnPaint, вызывал родительскую версию и поверх полученного изображения кнопки дорисовывал картинку своими силами.

Исходя из этого, есть у меня сильное подозрение, что стандартные контролы, вид которых управляется темой, нельзя просто так взять и поменять. Конечно, остаётся ещё вероятность, что существуют какие-то хитрые вызовы; или что тогда их не было, а теперь появились (всё-таки много времени прошло)…
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re: Как изменить цвет кнопки?
От: okon  
Дата: 17.10.19 02:04
Оценка: +1 -2
ЕМ>Все действительно настолько плохо, или я где-то чего не догоняю?

Потом народ спрашивает а чем WPF лучше.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re: Как изменить цвет кнопки?
От: small_cat Россия  
Дата: 17.10.19 05:22
Оценка:
Доброго времени.

Нет, это все не работает, ибо стандартные контролы.
Можно время не тратить, а сразу искать стороннее/писать своё.
- Простите, профессор, не пса, а когда он уже был человеком.
— То-есть он говорил? Это еще не значит быть человеком. (с) Булгаков
Re[2]: Как изменить цвет кнопки?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 17.10.19 07:59
Оценка:
Здравствуйте, okon, Вы писали:

O>Потом народ спрашивает а чем WPF лучше.


А оно лучше?
Re[2]: Как изменить цвет кнопки?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 17.10.19 08:01
Оценка:
Здравствуйте, small_cat, Вы писали:

_>Нет, это все не работает, ибо стандартные контролы.


Грустно. По сути, мне в некоторых случаях нужно просто выделить кнопку, чтобы указать на ситуацию, в которой ее требуется нажать. Тогда придется вешать значок, рисовать рамку или еще что-то подобное...
Re[3]: Как изменить цвет кнопки?
От: okon  
Дата: 17.10.19 08:05
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, okon, Вы писали:


O>>Потом народ спрашивает а чем WPF лучше.


ЕМ>А оно лучше?


там цвет кнопки и все остальное , в том числе лейаут контролов, менять ощутимо проще.
Необходимость в использовании сторонних компонент как правило отпадает, кастомные писать получаетя не так сложно и не дорого.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Отредактировано 17.10.2019 8:08 okon . Предыдущая версия . Еще …
Отредактировано 17.10.2019 8:08 okon . Предыдущая версия .
Re[4]: Как изменить цвет кнопки?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 17.10.19 09:07
Оценка:
Здравствуйте, okon, Вы писали:

O>там цвет кнопки и все остальное , в том числе лейаут контролов, менять ощутимо проще.

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

Любой фреймворк имеет какие-то ограничения. Поначалу кажется, что все просто, красиво и выразительно, а потом, когда привыкнешь, непременно вылезет какая-нибудь хрень, на борьбу с которой уйдет больше времени, чем было сэкономлено. Я пару раз напарывался, с тех пор опасаюсь.
Re[5]: Как изменить цвет кнопки?
От: okon  
Дата: 17.10.19 09:16
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, okon, Вы писали:


O>>там цвет кнопки и все остальное , в том числе лейаут контролов, менять ощутимо проще.

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

ЕМ>Любой фреймворк имеет какие-то ограничения. Поначалу кажется, что все просто, красиво и выразительно, а потом, когда привыкнешь, непременно вылезет какая-нибудь хрень, на борьбу с которой уйдет больше времени, чем было сэкономлено. Я пару раз напарывался, с тех пор опасаюсь.


есть замороченные вещи, но не могу придумать пример который в других UI фреймворках для Windows делается проще.
обычно то что сложно в WPF еще сложнее в других, может я просто плохо знаю WPF и другие фреймворки и не могу придумать пример.
Было бы интересно услышать опыт кто работает с ними много.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Re[3]: Как изменить цвет кнопки?
От: wildwind Россия  
Дата: 17.10.19 10:19
Оценка: +2
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Грустно. По сути, мне в некоторых случаях нужно просто выделить кнопку, чтобы указать на ситуацию, в которой ее требуется нажать. Тогда придется вешать значок, рисовать рамку или еще что-то подобное...


Вообще хорошим тоном считается не полагаться только на цвет. Так что лучше нарисуй рамку.
Re[4]: Как изменить цвет кнопки?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 17.10.19 10:24
Оценка: +1
Здравствуйте, wildwind, Вы писали:

W>Вообще хорошим тоном считается не полагаться только на цвет. Так что лучше нарисуй рамку.


Я в своем минимализме как-то и забыл, что, кроме классического серого фона, существуют еще и хитрораскрашенные темы.
Re[5]: Как изменить цвет кнопки?
От: qaz77  
Дата: 18.10.19 09:26
Оценка: 10 (1)
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Я в своем минимализме как-то и забыл, что, кроме классического серого фона, существуют еще и хитрораскрашенные темы.

Для рисования в контексте текущей визуальной темы есть функция DrawThemeBackground и ее компаньоны. Также надо учитывать всякие специальные состояния: default, hot и т.п. И цвет фона там может быть не один, а градиенты или более хитрые текстуры.

Вот пример использования из MSDN:
if (_hTheme)
{
  if (IsThemeBackgroundPartiallyTransparent(_hTheme, BP_PUSHBUTTON, _iStateId))
  {
    DrawThemeParentBackground(_hwnd, hdcPaint, prcPaint);
  }

  DrawThemeBackground(_hTheme,
                    hdcPaint,
                    BP_PUSHBUTTON,
                    _iStateId,
                    &rcClient,
                    prcPaint);
}


Печаль в том, что для классической темы это как раз не работает.
Надо проверять активность темы для клиентской части окон текущего процесса и, если темы отключены, рисовать через древний DrawFrameControl.
Re[5]: Как изменить цвет кнопки?
От: wildwind Россия  
Дата: 18.10.19 10:23
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Я в своем минимализме как-то и забыл, что, кроме классического серого фона, существуют еще и хитрораскрашенные темы.


Существуют еще и люди с особенностями зрения.
Re[6]: Как изменить цвет кнопки?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 18.10.19 10:54
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Существуют еще и люди с особенностями зрения.


Ну и как в таких условиях выделить кнопку, чтобы показать, что она имеет основание быть нажатой? Рисовать вокруг нее рамку, плавно меняющую цвет, чтобы ее увидел и каждый дальтоник?
Re[7]: Как изменить цвет кнопки?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 18.10.19 11:48
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Ну и как в таких условиях выделить кнопку, чтобы показать, что она имеет основание быть нажатой? Рисовать вокруг нее рамку, плавно меняющую цвет, чтобы ее увидел и каждый дальтоник?


А ещё озвучивать процесс, чтобы и слепые могли быть в курсе.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[7]: Как изменить цвет кнопки?
От: wildwind Россия  
Дата: 18.10.19 12:24
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Ну и как в таких условиях выделить кнопку, чтобы показать, что она имеет основание быть нажатой? Рисовать вокруг нее рамку, плавно меняющую цвет, чтобы ее увидел и каждый дальтоник?


Да просто рамки или подчеркивания системного цвета должно быть достаточно.
Но я бы еще подумал, если в данной ситуации нужно нажимать строго определенную кнопку, то может её того... и нажимать программно, не отвлекая пользователя?
Re[7]: Как изменить цвет кнопки?
От: RonWilson Россия  
Дата: 18.10.19 12:31
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, wildwind, Вы писали:


W>>Существуют еще и люди с особенностями зрения.


ЕМ>Ну и как в таких условиях выделить кнопку, чтобы показать, что она имеет основание быть нажатой? Рисовать вокруг нее рамку, плавно меняющую цвет, чтобы ее увидел и каждый дальтоник?


не надо ничего рисовать, просто сделайте пульсирующую кнопку (+- высота и длина по таймеру) с тикающим фоновым звуком
Re[8]: Как изменить цвет кнопки?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 18.10.19 13:10
Оценка:
Здравствуйте, wildwind, Вы писали:

W>Но я бы еще подумал, если в данной ситуации нужно нажимать строго определенную кнопку, то может её того... и нажимать программно, не отвлекая пользователя?


Не, по этой кнопке открывается одно из окно виндовых настроек. Так-то она просто для удобства, но, если системные настройки неподходящие — надо пользователя навести на мысль, что надо туда заглянуть.
Re: Как изменить цвет кнопки?
От: Pavel Dvorkin Россия  
Дата: 20.10.19 03:10
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

В крайнем случае сабклассинг этой кнопки, свой обработчик WM_PAINT, в нем залить нужной кистью. Должно сработать, ибо не зависит от типа контрола, общий механизм.
With best regards
Pavel Dvorkin
Re[2]: Как изменить цвет кнопки?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 20.10.19 10:13
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>В крайнем случае сабклассинг этой кнопки, свой обработчик WM_PAINT, в нем залить нужной кистью.


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