Кисти фона и переднего плана

48

Все элементы управления имеют фон (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. Однако кнопке можно придать новый облик (с указанной вами рамкой) с помощью шаблонов.

Пройди тесты
Лучший чат для C# программистов