Blog. Just Blog

Как менять цвета элементов диалогового окна на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
По умолчанию цвета диалоговых окон и элементов управления в приложениях соответствуют установленной палитре Windows. Но иногда бывает необходимо выделить другим цветом какой-нибудь текст в диалоговом окне, или же вообще раскрасить все окно в нужный вам цвет. Это сделать очень легко, надо лишь знать порядок вывода на экран диалоговых окон и их содержимого. При отрисовке каждого элемента диалогового окна ему обязательно передается одно из следующих сообщений: WM_CTLCOLORDLG - отрисовка самого окна, WM_CTLCOLORBTN - отрисовка кнопок, WM_CTLCOLOREDIT - отрисовка полей редактирования, WM_CTLCOLORSTATIC - отрисовка статических элементов, WM_CTLCOLORLISTBOX - отрисовка комбобоксов и выпадающих списков, WM_CTLCOLORMSGBOX - вывод окна сообщений и WM_CTLCOLORSCROLLBAR - отрисовка полосы прокрутки. Обработчик для всех этих сообщений может быть один. Главное, чтобы на этапе инициализации окна был создан объект "кисть" с фоновым цветом главного окна. Именно это значение должен всегда возвращать обработчик сообщение изменения цвета. Предварительный каркас такого приложения выглядит примерно так:
  1. ; Обработчик диалогового окна
  2. proc DialogProc hwnddlg,msg,wparam,lparam
  3.         ...
  4.         ; Обработка сообщения инициализации окна
  5.         cmp     [msg],WM_INITDIALOG
  6.         je      wminitdialog
  7.  
  8.         ; Обработка всех сообщений, связанных с установкой цвета
  9.         cmp     [msg],WM_CTLCOLORDLG
  10.         je      color
  11.         cmp     [msg],WM_CTLCOLORBTN
  12.         je      color
  13.         cmp     [msg],WM_CTLCOLOREDIT
  14.         je      color
  15.         cmp     [msg],WM_CTLCOLORSTATIC
  16.         je      color
  17.         cmp     [msg],WM_CTLCOLORLISTBOX
  18.         je      color
  19.         cmp     [msg],WM_CTLCOLORMSGBOX
  20.         je      color
  21.         cmp     [msg],WM_CTLCOLORSCROLLBAR
  22.         je      color
  23.         ...
  24.  
  25.         ; Обработка инициализации окна
  26. wminitdialog:
  27.         ; Основной цвет фона окна в формате RGB
  28.         clrMain = 0012FFFFh
  29.         ; Создать объект фоновой кисти для всего окна
  30.         invoke  CreateSolidBrush,clrMain
  31.         mov     [hBrushBack], eax
  32.  
  33.         jmp     processed
В этом примере все обработчики заданы по максимуму, в вашем приложении можно оставить только необходимое, например, только обработку статических элементов. При написании обработчиков учтите следующие особенности: для read-only или отключенных элементов EDIT сообщение WM_CTLCOLOREDIT не посылается, вместо него посылается сообщение WM_CTLCOLORSTATIC. Цвет текста для кнопок BS_AUTOCHECKBOX и BS_AUTORADIOBUTTON применяется только к их тексту, а флажок кнопок закрашен системно-определенным цветом (обычно черным). Цвет текста для BS_GROUPBOX применяется только к тексту заголовка, но не к линии границы элемента. Также обратите внимание, что цвет задается значениями RGB в трех младших байтах DWORD, при этом оставшийся байт игнорируется.

Теперь рассмотрим сам обработчик установки цвета. В простейшем варианте он выглядит примерно так:
  1.         ; Обработка сообщения установки цвета
  2. color:
  3.         ; Цвета текста и фона элементов
  4.         clrFore = 000000FFh
  5.         clrBack = 0012FFFFh
  6.  
  7.         ; Установить цвет текста
  8.         invoke  SetTextColor,[wparam],clrFore
  9.         ; Установить цвет фона
  10.         invoke  SetBkColor,[wparam],clrBack
  11.         ; Установить режим смешивания фоновых цветов
  12.         invoke  SetBkMode,[wparam],OPAQUE
  13.  
  14.         ; Вернуть объект фоновой кисти окна
  15.         mov     eax,[hBrushBack]
  16.         jmp     processed
При поступлении сообщения на изменение цвета, надо просто установить нужный цвет фона и текста элементу, контекст которого передан в значении wparam сообщения. После этого обработчик обязательно должен вернуть объект фоновой кисти для всего окна, созданной на этапе инициализации окна. При таком обработчике будет просто создано окно нужного цвета, а всем его элементам также будут раскрашены нужным цветом. Но эти цвета будут одинаковы для окна и всех его элементов.

Теперь усовершенствуем обработчик установки цвета, чтобы мы могли изменять цвета только нужных нам элементов и только в тот момент, когда нам это надо. Для этого воспользуемся удобнейшими функциями SetProp и GetProp. Вкратце, они позволяют присваивать любому окну или элементу окна произвольное свойство, которое остается закрепленным за ним, пока окно не будет закрыто. В нашем случае где-то в приложении мы будем устанавливать отдельным элементам диалогового окна нужный нам цвет фона и цвет текста, а в обработчике установки цвета будем устанавливать эти значения. Если у элемента не установлены значения цвета, то такой элемент обрабатываться не будет.
  1. ; Определение констант свойств
  2. PROP_COLOR      = 101
  3. PROP_BACK       = 102
  4.  
  5.         ; Обработка сообщения установки цвета
  6.         ; В [lparam] - хэндл окна элемента, которому устанавливается цвет
  7. color:
  8.         ; Получить значение цвета текста
  9.         invoke  GetProp,[lparam],PROP_COLOR
  10.         or      eax,eax
  11.         jz      @f
  12.         ; Установить цвет текста
  13.         invoke  SetTextColor,[wparam],eax
  14. @@:
  15.         ; Получить значение цвета фона
  16.         invoke  GetProp,[lparam],PROP_BACK
  17.         or      eax,eax
  18.         jz      @f
  19.         ; Установить цвет фона
  20.         invoke  SetBkColor,[wparam],eax
  21. @@:
  22.         ; Установить режим смешивания фоновых цветов
  23.         invoke  SetBkMode,[wparam],OPAQUE
  24.  
  25.         ; Вернуть объект фоновой кисти окна
  26.         mov     eax,[hBrushBack]
  27.         jmp     processed
Обновление элемента выполняется примерно так. Этот код можно вызывать в любой момент времени после создания окна:
  1.         ; Обновить окно STATIC1
  2.         invoke  GetDlgItem,[hwnddlg],ID_ST1
  3.         mov     ebx,eax
  4.  
  5.         ; Установить значение цвета текста
  6.         invoke  SetProp,ebx,PROP_COLOR,clrFore
  7.  
  8.         ; Установить значение цвета фона
  9.         invoke  SetProp,ebx,PROP_BACK,clrBack
  10.  
  11.         ; Перерисовать элемент с новым цветом
  12.         invoke  InvalidateRect,ebx,NULL,TRUE
Если требуется поменять только цвет текста, то значение цвета фона предварительно получите при помощи функции GetSysColor с параметром COLOR_WINDOW. Аналогично, если требуется поменять только цвет фона. Как видите, ничего сложного в управлении цветом нет. Но здесь, как и в любом другом деле, главное не переборщить.

В приложении две программы с исходными текстами. Первая просто отрисовывает диалоговое окно с элементами заданного цвета, вторая позволяет менять цвета текста и фона отдельных элементов по нажатию на кнопку.

Пример программ с исходными текстами (FASM)Пример программ с исходными текстами (FASM)

Color.Window.Demo.zip (5,800 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 13475 | Комментариев: 12

Метки: Assembler, окна
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Alex (01.05.2020 в 11:33):
Спасибо.
Все нашел, где я тупил.
Просто мозг вскипел.
ManHunter (01.05.2020 в 08:25):
Ну вот, к штанам добавляется рубашка через ноги. Чем принципиально отличается создание статиков на лету от статиков в ресурсах? Нарисовал в нужный момент сколько надо статиков, потом отправил InvalidateRect их родительскому окну и готово, никаких енумов, никаких GetWindowLong.
https://www.upload.ee/files/11...lor.zip.html
Дальше или сам или за деньги.
Alex (01.05.2020 в 06:52):
Я внимательно прочитал вашу статью, очень хорошая и главное доступно все описано. Но в вашей статье статики выполнены при помощи ресурсов, а у меня все делается при помощи CreateWindowEx, как Child. Выбираю контрол при помощи EnumChildWindows и обратного вызова GetWindowLong. По этому у меня закрашивается только последний.
ManHunter (28.04.2020 в 10:37):
Насколько я знаю - нет. Да и смысл? Это как штаны через голову надевать, есть же нормальные рабочие решения. Как работать с отдельным элементом, хоть статиком, хоть едитом, я в статье написал.
Alex (28.04.2020 в 07:35):
Можно ли поменять цвет отдельного статика из нескольких,
не используя сообщение WM_CTLCOLORSTATIC.
Допустим как то через WM_PAINT
ManHunter (12.02.2015 в 17:24):
Поменять нельзя. Можно нарисовать свой static с какой угодно иконкой/битмапом и потом эмулировать работу чекбокса, меняя иконку/битмап у статика в зависимости от его текущего состояния. Это хорошо делается через субклассирование.
Евгений (12.02.2015 в 17:21):
Здравствуйте. Не подскажете, как можно поменять цвет чекбокса? и вообще перерисовать его можно как-то или битмап наложить?
ManHunter (27.10.2013 в 13:56):
"Buttons with the BS_PUSHBUTTON, BS_DEFPUSHBUTTON, or BS_PUSHLIKE styles do not use the returned brush. Buttons with these styles are always drawn with the default system colors"

MSDN -> BS_OWNERDRAW, WM_DRAWITEM, DrawItem
Придется самому рисовать кнопку, используя стиль BS_OWNERDRAW, затем отлавливать и обрабатывать WM_DRAWITEM. Не самая тривиальная задача, но вполне решаемая.

http://stackoverflow.com/quest...ton-winapi-c

Как вариант - использовать картинки. Вот хороший пример:
http://www.johnfindlay.plus.co...g/ownbut.zip
mikado3333 (26.10.2013 в 07:16):
ManHunter, подскажите а как поменять цвет  у кнопки созданной функциией "CreateWindowEx"?
brute (10.01.2013 в 18:37):
нашел всё-таки пример с кнопкой: C:\masm32\examples\exampl07\butntest
но мне в нем не разобраться - слишком сложно наворочено..
ManHunter (09.01.2013 в 12:41):
brute, ну так скомпилированный файл - это ж и есть практически ассемблер :) Дизассемблируешь твой пример, получаешь ассемблерный код. Компилируешь обратно и получаешь красивую кнопочку на асме.
PROP_COLOR и PROP_BACK - это что-то типа индексов в массиве свойств. Можно задавать просто цифрами, но так кошернее. А описания *Prop лучше смотреть на MSDN, там все очень хорошо расписано.
brute (09.01.2013 в 12:35):
asm, конечно, крут, но вот такую кнопочку на нём ни в жизнь не заделать:
http://webfile.ru/6306578
в первом примере (да и во втором) не работают цвета кнопок и длгфрейма - сие и неудивительно - подобных примеров в инете (рдсн и папке масм32) не нашёл. Не совсем понятно про  функции Prop (опять же из-за отсутствия примеров в других источниках) - они типа флажков? зачем нужны константы PROP_COLOR и PROP_BACK? Насколько нужны эти функции - можно ли менять цвет как в первом примере, обрабатывая on_click?

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.0073 сек.) / Память: 4.5 Mb
Наверх