По умолчанию цвета диалоговых окон и элементов управления в приложениях соответствуют установленной палитре Windows. Но иногда бывает необходимо выделить другим цветом какой-нибудь текст в диалоговом окне, или же вообще раскрасить все окно в нужный вам цвет. Это сделать очень легко, надо лишь знать порядок вывода на экран диалоговых окон и их содержимого. При отрисовке каждого элемента диалогового окна ему обязательно передается одно из следующих сообщений:
WM_CTLCOLORDLG - отрисовка самого окна,
WM_CTLCOLORBTN - отрисовка кнопок,
WM_CTLCOLOREDIT - отрисовка полей редактирования,
WM_CTLCOLORSTATIC - отрисовка статических элементов,
WM_CTLCOLORLISTBOX - отрисовка комбобоксов и выпадающих списков,
WM_CTLCOLORMSGBOX - вывод окна сообщений и
WM_CTLCOLORSCROLLBAR - отрисовка полосы прокрутки. Обработчик для всех этих сообщений может быть один. Главное, чтобы на этапе инициализации окна был создан объект "кисть" с фоновым цветом главного окна. Именно это значение должен всегда возвращать обработчик сообщение изменения цвета. Предварительный каркас такого приложения выглядит примерно так:
; Обработчик диалогового окна
proc DialogProc hwnddlg,msg,wparam,lparam
...
; Обработка сообщения инициализации окна
cmp [msg],WM_INITDIALOG
je wminitdialog
; Обработка всех сообщений, связанных с установкой цвета
cmp [msg],WM_CTLCOLORDLG
je color
cmp [msg],WM_CTLCOLORBTN
je color
cmp [msg],WM_CTLCOLOREDIT
je color
cmp [msg],WM_CTLCOLORSTATIC
je color
cmp [msg],WM_CTLCOLORLISTBOX
je color
cmp [msg],WM_CTLCOLORMSGBOX
je color
cmp [msg],WM_CTLCOLORSCROLLBAR
je color
...
; Обработка инициализации окна
wminitdialog:
; Основной цвет фона окна в формате RGB
clrMain = 0012FFFFh
; Создать объект фоновой кисти для всего окна
invoke CreateSolidBrush,clrMain
mov [hBrushBack], eax
jmp processed
В этом примере все обработчики заданы по максимуму, в вашем приложении можно оставить только необходимое, например, только обработку статических элементов. При написании обработчиков учтите следующие особенности: для read-only или отключенных элементов EDIT сообщение WM_CTLCOLOREDIT не посылается, вместо него посылается сообщение WM_CTLCOLORSTATIC. Цвет текста для кнопок BS_AUTOCHECKBOX и BS_AUTORADIOBUTTON применяется только к их тексту, а флажок кнопок закрашен системно-определенным цветом (обычно черным). Цвет текста для BS_GROUPBOX применяется только к тексту заголовка, но не к линии границы элемента. Также обратите внимание, что цвет задается значениями RGB в трех младших байтах DWORD, при этом оставшийся байт игнорируется.
Теперь рассмотрим сам обработчик установки цвета. В простейшем варианте он выглядит примерно так:
; Обработка сообщения установки цвета
color:
; Цвета текста и фона элементов
clrFore = 000000FFh
clrBack = 0012FFFFh
; Установить цвет текста
invoke SetTextColor,[wparam],clrFore
; Установить цвет фона
invoke SetBkColor,[wparam],clrBack
; Установить режим смешивания фоновых цветов
invoke SetBkMode,[wparam],OPAQUE
; Вернуть объект фоновой кисти окна
mov eax,[hBrushBack]
jmp processed
При поступлении сообщения на изменение цвета, надо просто установить нужный цвет фона и текста элементу, контекст которого передан в значении wparam сообщения. После этого обработчик обязательно должен вернуть объект фоновой кисти для всего окна, созданной на этапе инициализации окна. При таком обработчике будет просто создано окно нужного цвета, а всем его элементам также будут раскрашены нужным цветом. Но эти цвета будут одинаковы для окна и всех его элементов.
Теперь усовершенствуем обработчик установки цвета, чтобы мы могли изменять цвета только нужных нам элементов и только в тот момент, когда нам это надо. Для этого воспользуемся удобнейшими функциями
SetProp и
GetProp. Вкратце, они позволяют присваивать любому окну или элементу окна произвольное свойство, которое остается закрепленным за ним, пока окно не будет закрыто. В нашем случае где-то в приложении мы будем устанавливать отдельным элементам диалогового окна нужный нам цвет фона и цвет текста, а в обработчике установки цвета будем устанавливать эти значения. Если у элемента не установлены значения цвета, то такой элемент обрабатываться не будет.
; Определение констант свойств
PROP_COLOR = 101
PROP_BACK = 102
; Обработка сообщения установки цвета
; В [lparam] - хэндл окна элемента, которому устанавливается цвет
color:
; Получить значение цвета текста
invoke GetProp,[lparam],PROP_COLOR
or eax,eax
jz @f
; Установить цвет текста
invoke SetTextColor,[wparam],eax
@@:
; Получить значение цвета фона
invoke GetProp,[lparam],PROP_BACK
or eax,eax
jz @f
; Установить цвет фона
invoke SetBkColor,[wparam],eax
@@:
; Установить режим смешивания фоновых цветов
invoke SetBkMode,[wparam],OPAQUE
; Вернуть объект фоновой кисти окна
mov eax,[hBrushBack]
jmp processed
Обновление элемента выполняется примерно так. Этот код можно вызывать в любой момент времени после создания окна:
; Обновить окно STATIC1
invoke GetDlgItem,[hwnddlg],ID_ST1
mov ebx,eax
; Установить значение цвета текста
invoke SetProp,ebx,PROP_COLOR,clrFore
; Установить значение цвета фона
invoke SetProp,ebx,PROP_BACK,clrBack
; Перерисовать элемент с новым цветом
invoke InvalidateRect,ebx,NULL,TRUE
Если требуется поменять только цвет текста, то значение цвета фона предварительно получите при помощи функции
GetSysColor с параметром COLOR_WINDOW. Аналогично, если требуется поменять только цвет фона. Как видите, ничего сложного в управлении цветом нет. Но здесь, как и в любом другом деле, главное не переборщить.
В приложении две программы с исходными текстами. Первая просто отрисовывает диалоговое окно с элементами заданного цвета, вторая позволяет менять цвета текста и фона отдельных элементов по нажатию на кнопку.