Кисти фона и переднего плана
48WPF --- Элементы управления WPF --- Кисти фона и переднего плана
Все элементы управления имеют фон (background) и передний план (foreground). Как правило, фоном является поверхность элемента управления (например, белая или серая область внутри кнопки), а передним планом — текст. В WPF цвет (но не содержимое) этих двух областей определяется с помощью свойств Background и Foreground соответственно.
Естественно ожидать, что свойства Background и Foreground должны использовать объекты цвета, как в приложениях на основе Windows Forms. Однако на самом деле эти свойства используют более универсальный объект — Brush (кисть). Он позволяет заливать содержимое фона и переднего плана сплошным цветом (с помощью кисти SolidColorBrush) или чем-то экзотическим (например, используя кисти LinearGradientBrush или TileBrush).
Указание цветов в коде
Предположим, что вы хотите задать внутри кнопки cmd поверхность голубого цвета. Вот код, позволяющий это сделать:
cmd.Background = new SolidColorBrush(Colors.AliceBlue);
Этот код создает новый объект SolidColorBrush с цветом, указанным с помощью статического свойства класса Colors. (Имена основаны на названиях цветов, которые поддерживаются большинством веб-браузеров.) Затем эта кисть определяется в качестве фоновой кисти кнопки, в результате чего фон кнопки становится светло-голубым.
Такой метод оформления кнопки не очень удобен. Он задает фоновый цвет кнопки в ее обычном состоянии (не нажата), но не изменяет цвет, который появляется при щелчке на кнопке (обычно более темный серый цвет). Чтобы настраивать все нюансы отображения кнопок, следует ознакомиться с шаблонами.
Можно также пользоваться системными цветами (они могут выбираться исходя из предпочтений пользователя) из перечисления System.Windows.SystemColors. Например:
cmd.Background = new SolidColorBrush(SystemColors.ControlColor);
Поскольку системные кисти используются часто, класс SystemColors предлагает также готовые свойства, возвращающие объекты SolidColorBrush. Ниже показано, как их применять:
cmd.Background = SystemColors.ControlBrush;
В обоих этих примерах имеется небольшая проблема. Если системный цвет будет изменен после выполнения этого кода, кнопка не будет обновлена, и новый цвет не будет применен. По сути, этот код делает мгновенный снимок текущего цвета или кисти.
Чтобы программа могла изменять себя в ответ на изменения в конфигурации, необходимо применять динамические ресурсы. Классы Colors и SystemColors предлагают удобные сокращения, однако это не единственный способ задать цвет. Вы можете, например, создать объект Color, указав значения R, G и В (красной, зеленой и синей составляющих). Каждое из этих значений является числом из диапазона 0-255.
Можно также сделать цвет частично прозрачным, используя значение альфа-канала и вызвав метод Color.FromArgb(). Значение альфа-канала, равное 255, соответствует полной непрозрачности, а значение 0 — полной прозрачности:
btn.Background = new SolidColorBrush(Color.FromArgb(90, 0xF0, 0x00, 0xFF));
Стандарт RGB полезен, поскольку применяется во многих других программах. Например, можно получить RGB-значение цвета в программе для рисования и использовать этот же цвет в WPF-приложении. Однако не исключено, что другие устройства (например, принтеры) могут поддерживать более широкий диапазон цветов. По этой причине был создан альтернативный стандарт scRGB, в котором каждый компонент цвета (альфа-канал, красный, зеленый и синий) представлен 64-битовыми значениями.
Структура класса Color в WPF поддерживает оба подхода. Она включает как набор стандартных свойств RGB (A, R, G и В), так и набор свойств scRGB (ScA, ScR, ScG и ScB). Эти свойства связаны между собой, поэтому если задать свойство R, то соответственно изменится и свойство ScR.
Взаимосвязь между значениями RGB и значениями scRGB не является линейной. Значение 0 в системе RGB соответствует значению 0 в scRGB, 255 в RGB соответствует 1 в scRGB, а все значения в диапазоне 0-255 в RGB представлены в scRGB как десятичные значения из диапазона от 0 до 1.
Задание цветов в XAML
При задании цвета фона или переднего плана в XAML можно воспользоваться удобным сокращением. Вместо определения объекта Brush можно указать наименование или значение цвета. Компилятор WPF автоматически создаст объект SolidColorBrush с выбранным цветом и будет применять этот объект для фона или переднего плана. Вот пример с использованием имени цвета:
<Button Background="Red">А Button</Button>
Он эквивалентен следующему многострочному фрагменту:
<Button>A Button
<Button.Background>
<SolidColorBrush Color="Red" />
</Button.Background>
</Button>
Если нужен другой тип кисти (например, LinearGradientBrush), для рисования фона потребуется использовать более длинную форму.
Если необходим код цвета, придется пользоваться менее удобным синтаксисом, в котором значения R, G и В представляются в шестнадцатеричном формате. Доступны два формата: #rrggbb или #aarrggbb (они отличаются тем, что второй формат содержит значение альфа-канала). Для задания значений A, R, G и В, нужно только по две цифры, поскольку все они представляются в шестнадцатеричной форме. Ниже показан пример, который создает тот же цвет, что и в предыдущем фрагменте кода, с помощью формата aarrggbb:
<Button Background="#FFFFOOOO">A Button</Button>
Здесь значением альфа-канала является FF (255), значением красной составляющей — FF (255), а зеленая и синяя составляющие равны 0.
Кисти поддерживают автоматическое уведомление об изменениях. То есть если прикрепить кисть к элементу управления и изменить ее, элемент управления обновляет себя соответствующим образом. Это возможно потому, что кисти являются потомками класса System.Windows.Freezable. Название этого класса (freezable — замораживаемый) объясняется тем, что все такие объекты имеют два состояния: изменяемое состояние и состояние только для чтения ("замороженное").
Background и Foreground — не единственные свойства, которые можно определить с помощью кисти. Свойства BorderBrush и BorderThickness позволяют нарисовать рамку вокруг элементов управления (и некоторых других элементов вроде Border).
Свойство BorderBrush принимает указанную кисть, а свойство BorderThickness — ширину рамки в не зависящих от устройства единицах. Чтобы рамка стала видимой, необходимо установить оба свойства.
Некоторые элементы управления не поддерживают использование свойств BorderBrush и BorderThickness. Объект Button игнорирует их полностью, поскольку определяет свой фон и рамку с помощью декоратора ButtonChrome. Однако кнопке можно придать новый облик (с указанной вами рамкой) с помощью шаблонов.