Мы уже научились рисовать простые фигуры и узнали, где и как это можно делать. Давайте теперь посмотрим на процесс рисования с учетом основной его характеристики — цвета.
За цвет в .NET отвечает структура Color. Поля этой структуры изменять нельзя, поэтому цвет задается только на этапе инициализации и не может меняться. Самое интересное — у этой структуры нет конструктора, принимающего цвет или что-либо еще. Есть только конструктор по умолчанию, который просто производит инициализацию:
Color c = new Color();
Цвет в .NET представляется в виде четырех составляющих: красного, зеленого, синего и прозрачного. У структуры Color есть четыре соответствующих свойства типа byte (а значит, они будут изменяться от 0 до 255):
В сумме эти свойства занимают в памяти 4 байта (32 бита). Смешением этих составляющих можно получить любой цвет из 16 миллионов возможных. Человеческий глаз не способен различать столько цветов.
А теперь самое интересное — так как составляющие цвета доступны только для чтения, то после создания мы не можем изменить цвет, и следующий код завершится ошибкой на второй строке:
Color c = new Color(); c.R = 255; // Ошибка! Изменять нельзя!
Но как же тогда создать нужный нам цвет, если у нас нет конструктора и нет возможности менять свойства? С помощью статичных методов Color, например:
FromArgb(), FromName(), FromKnownColor().
Есть несколько перегруженных вариантов метода FromArgb(). Например, цвет может быть создан на основе числа типа int. Тип данных int состоит из 32 битов — как раз столько и нужно, чтобы хранить все четыре составляющие цвета. Метод может сделать обратную операцию — разбить число int на четыре составляющие byte.
Более удобным вариантом мне представляется метод FromArgb(), получающий четыре числа для каждой составляющей:
Color.FromArgb(прозрачность, красный, зеленый, синий);
Следующая строка создает абсолютно непрозрачный красный цвет (попробуйте создать приложение и поиграть с цветом):
Color c = Color.FromArgb(255, 255, 0, 0);
Не знаю, зачем это сделано, но в таком варианте метод получает составляющие в качестве типа данных int. Это значит, что вы можете в любом параметре указать число, большее 255, но во время выполнения программы это приведет к ошибке. Логичнее было бы сделать тип параметров byte. Почему int, я объяснить не могу.
Следующий способ получить цвет — воспользоваться методом FromName(), который принимает в качестве параметра название цвета в виде строки и пытается превратить его в структуру Color. Например, следующая строка создает зеленый цвет по его имени "Green":
Color c = Color.FromName("Green");
Если приведение невозможно и цвет, соответствующий названию, не найден, то метод вернет структуру Color, у которой все составляющие будут равны нулю. Сообщение об ошибке генерироваться не будет.
Следующий вариант — использовать метод FromKnownColor(). Этот метод получает в качестве параметра перечисление KnownColor, которое состоит из множества названий цветов и названий системных цветов, которые входят в другие перечисления, такие как SystemColors или Color:
Color c = Color.FromKnownColor(KnownColor.ButtonShadow);
Системные цвета проще получать через перечисление SystemColors. Например, следующая строка инициализирует переменную цветом, который использует система для рисования тени для кнопки:
Color c = SystemColors.ButtonShadow;
Если нужен один из основных цветов, то можно использовать статичные свойства самой структуры Color. У нее уже есть предопределенные значения для основных цветов. Например, следующая строка использует предопределенный красный цвет для создания переменной:
Color c = Color.Red;
У структуры Color есть еще несколько интересных свойств: