Сегодня утром приспичило сделать изменение цвета [фона] верхней поверхности кнопки (обычный 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 — будут дергаться другие окна, а им это ни к чему?
Все действительно настолько плохо, или я где-то чего не догоняю?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Все действительно настолько плохо, или я где-то чего не догоняю?
Давно-давно, когда операционки были маленькими, процессоры — 32-битными, а памяти хватало не только на запуск браузера, заинтересовался я, как можно сделать кнопку с картинкой при включённых стилях WinXP. MFC-шный CButton::SetIcon (вроде бы, опирается на BM_SETIMAGE) картиночку-то добавлял, но саму кнопку превращал в прямоугольную классическую, что выглядело, мягко говоря, неуместно. В итоге мне тогда удалось нагуглить лишь один рабочий вариант, который наследовался от класса CButton, переопределял OnPaint, вызывал родительскую версию и поверх полученного изображения кнопки дорисовывал картинку своими силами.
Исходя из этого, есть у меня сильное подозрение, что стандартные контролы, вид которых управляется темой, нельзя просто так взять и поменять. Конечно, остаётся ещё вероятность, что существуют какие-то хитрые вызовы; или что тогда их не было, а теперь появились (всё-таки много времени прошло)…
ЕМ>Все действительно настолько плохо, или я где-то чего не догоняю?
Потом народ спрашивает а чем WPF лучше.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Здравствуйте, small_cat, Вы писали:
_>Нет, это все не работает, ибо стандартные контролы.
Грустно. По сути, мне в некоторых случаях нужно просто выделить кнопку, чтобы указать на ситуацию, в которой ее требуется нажать. Тогда придется вешать значок, рисовать рамку или еще что-то подобное...
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Здравствуйте, okon, Вы писали:
O>>Потом народ спрашивает а чем WPF лучше.
ЕМ>А оно лучше?
там цвет кнопки и все остальное , в том числе лейаут контролов, менять ощутимо проще.
Необходимость в использовании сторонних компонент как правило отпадает, кастомные писать получаетя не так сложно и не дорого.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Здравствуйте, okon, Вы писали:
O>там цвет кнопки и все остальное , в том числе лейаут контролов, менять ощутимо проще. O>Необходимость в использовании сторонних компонент как правило отпадает, кастомные писать получаетя не так сложно и не дорого.
Любой фреймворк имеет какие-то ограничения. Поначалу кажется, что все просто, красиво и выразительно, а потом, когда привыкнешь, непременно вылезет какая-нибудь хрень, на борьбу с которой уйдет больше времени, чем было сэкономлено. Я пару раз напарывался, с тех пор опасаюсь.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Здравствуйте, okon, Вы писали:
O>>там цвет кнопки и все остальное , в том числе лейаут контролов, менять ощутимо проще. O>>Необходимость в использовании сторонних компонент как правило отпадает, кастомные писать получаетя не так сложно и не дорого.
ЕМ>Любой фреймворк имеет какие-то ограничения. Поначалу кажется, что все просто, красиво и выразительно, а потом, когда привыкнешь, непременно вылезет какая-нибудь хрень, на борьбу с которой уйдет больше времени, чем было сэкономлено. Я пару раз напарывался, с тех пор опасаюсь.
есть замороченные вещи, но не могу придумать пример который в других UI фреймворках для Windows делается проще.
обычно то что сложно в WPF еще сложнее в других, может я просто плохо знаю WPF и другие фреймворки и не могу придумать пример.
Было бы интересно услышать опыт кто работает с ними много.
”Жить стало лучше... но противнее. Люди которые ставят точку после слова лучше становятся сторонниками Путина, наши же сторонники делают акцент на слове противнее ( ложь, воровство, лицемерие, вражда )." (с) Борис Немцов
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Грустно. По сути, мне в некоторых случаях нужно просто выделить кнопку, чтобы указать на ситуацию, в которой ее требуется нажать. Тогда придется вешать значок, рисовать рамку или еще что-то подобное...
Вообще хорошим тоном считается не полагаться только на цвет. Так что лучше нарисуй рамку.
Здравствуйте, Евгений Музыченко, Вы писали: ЕМ>Я в своем минимализме как-то и забыл, что, кроме классического серого фона, существуют еще и хитрораскрашенные темы.
Для рисования в контексте текущей визуальной темы есть функция 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.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Я в своем минимализме как-то и забыл, что, кроме классического серого фона, существуют еще и хитрораскрашенные темы.
Здравствуйте, wildwind, Вы писали:
W>Существуют еще и люди с особенностями зрения.
Ну и как в таких условиях выделить кнопку, чтобы показать, что она имеет основание быть нажатой? Рисовать вокруг нее рамку, плавно меняющую цвет, чтобы ее увидел и каждый дальтоник?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Ну и как в таких условиях выделить кнопку, чтобы показать, что она имеет основание быть нажатой? Рисовать вокруг нее рамку, плавно меняющую цвет, чтобы ее увидел и каждый дальтоник?
А ещё озвучивать процесс, чтобы и слепые могли быть в курсе.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Ну и как в таких условиях выделить кнопку, чтобы показать, что она имеет основание быть нажатой? Рисовать вокруг нее рамку, плавно меняющую цвет, чтобы ее увидел и каждый дальтоник?
Да просто рамки или подчеркивания системного цвета должно быть достаточно.
Но я бы еще подумал, если в данной ситуации нужно нажимать строго определенную кнопку, то может её того... и нажимать программно, не отвлекая пользователя?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Здравствуйте, wildwind, Вы писали:
W>>Существуют еще и люди с особенностями зрения.
ЕМ>Ну и как в таких условиях выделить кнопку, чтобы показать, что она имеет основание быть нажатой? Рисовать вокруг нее рамку, плавно меняющую цвет, чтобы ее увидел и каждый дальтоник?
не надо ничего рисовать, просто сделайте пульсирующую кнопку (+- высота и длина по таймеру) с тикающим фоновым звуком
Здравствуйте, wildwind, Вы писали:
W>Но я бы еще подумал, если в данной ситуации нужно нажимать строго определенную кнопку, то может её того... и нажимать программно, не отвлекая пользователя?
Не, по этой кнопке открывается одно из окно виндовых настроек. Так-то она просто для удобства, но, если системные настройки неподходящие — надо пользователя навести на мысль, что надо туда заглянуть.
В крайнем случае сабклассинг этой кнопки, свой обработчик WM_PAINT, в нем залить нужной кистью. Должно сработать, ибо не зависит от типа контрола, общий механизм.