logo search
C#, 320 стр

Кисти и краски

Создадим в нашем проекте новую форму RandomShapes, в которой будем рисовать и закрашивать геометрические фигуры трех разных типов - эллипсы, сектора, прямоугольники. Для каждого типа фигуры будем использовать свой тип кисти: эллипсы будем закрашивать градиентной кистью, сектора - сплошной, а прямоугольники - узорной. Цвет фигуры, ее размеры и положение будем выбирать случайным образом. Рисование фигур будет инициироваться в обработчике события Click. При каждом щелчке кнопкой мыши на форме будут рисоваться три новых экземпляра фигур каждого типа. В отличие от кривых Безье, старые фигуры стираться не будут.

На рис. 24.15 показана форма после нескольких щелчков кнопки мыши. Конечно, черно-белый рисунок в книге не может передать цвета, особенно смену оттенков для градиентной кисти. На экране дисплея или цветном рисунке все выглядит красивее.

А теперь приведем программный код, реализующий рисование. Начнем, как обычно, с полей класса:

//fields

int cx,cy;

Graphics graph;

Brush brush;

Color color;

Random rnd;

Инициализация полей производится в методе MyInit, вызываемом конструктором класса:

Рис. 24.15.  Рисование кистями разного типа

void MyInit()

{

cx = ClientSize.Width;

cy = ClientSize.Height;

graph = CreateGraphics();

rnd = new Random();

}

Рассмотрим теперь основной метод, реализующий рисование фигур различными кистями:

void DrawShapes()

{

for(int i=0; i<3; i++)

{

//выбирается цвет - красный, желтый, голубой

int numcolor = rnd.Next(3);

switch (numcolor)

{

case 0:

color = Color.Blue; break;

case 1:

color = Color.Yellow; break;

case 2:

color = Color.Red; break;

}

//градиентной кистью рисуется эллипс,

//местоположение случайно

Point top = new Point(rnd.Next(cx), rnd.Next(cy));

Size sz = new Size(rnd.Next(cx-top.X), rnd.Next(cy-top.Y));

Rectangle rct = new Rectangle(top, sz);

Point bottom = top + sz;

brush = new LinearGradientBrush(top, bottom,

Color.White,color);

graph.FillEllipse(brush,rct);

//сплошной кистью рисуется сектор,

//местоположение случайно

top = new Point(rnd.Next(cx), rnd.Next(cy));

sz = new Size(rnd.Next(cx-top.X), rnd.Next(cy-top.Y));

rct = new Rectangle(top, sz);

brush = new SolidBrush(color);

graph.FillPie(brush,rct,30f,60f);

//узорной кистью рисуется прямоугольник,

//местоположение случайно

top = new Point(rnd.Next(cx), rnd.Next(cy));

sz = new Size(rnd.Next(cx-top.X), rnd.Next(cy-top.Y));

rct = new Rectangle(top, sz);

HatchStyle hs = (HatchStyle)rnd.Next(52);

brush = new HatchBrush(hs,Color.White, Color.Black);

graph.FillRectangle(brush,rct);

}

}

Приведу некоторые комментарии в дополнение к тем, что встроены в текст метода. Здесь многое построено на работе со случайными числами. Случайным образом выбирается один из возможных цветов для рисования фигуры, ее размеры и положение. Наиболее интересно рассмотреть создание кистей разного типа. Когда создается градиентная кисть.

brush = new LinearGradientBrush(top, bottom, Color.White,color);

то нужно в конструкторе кисти задать две точки и два цвета. Точки определяют интервал изменения оттенков цвета от первого до второго. В начальной точке имеет место первый цвет, в конечной - второй, в остальных точках - их комбинация. Разумно, как это сделано у нас, в качестве точек выбирать противоположные углы прямоугольника, ограничивающего рисуемую фигуру.

Наиболее просто задается сплошная кисть:

brush = new SolidBrush(color);

Для нее достаточно указать только цвет. Для узорной кисти нужно задать предопределенный тип узора, всего их возможно 52. В нашем примере тип узора выбирается случайным образом:

HatchStyle hs = (HatchStyle)rnd.Next(52);

brush = new HatchBrush(hs,Color.White, Color.Black);

Помимо первого аргумента, задающего тип узора, указываются еще два цвета - первый определяет цвет повторяющегося элемента, второй - цвет границы между элементами узора.

Непосредственное рисование кистью осуществляют методы группы Fill:

graph.FillEllipse(brush,rct);

graph.FillPie(brush,rct,30f,60f);

graph.FillRectangle(brush,rct);

Первый аргумент всегда задает кисть, а остальные зависят от типа рисуемой фигуры. Как правило, всегда задается прямоугольник, ограничивающий данную фигуру.

Вызов метода DrawShapes, как уже говорилось, встроен в обработчик события Click формы RandomShapes:

private void RandomShapes_Click(object sender, System.EventArgs e)

{

DrawShapes();

}

На этом поставим точку в рассмотрении данной темы. По сути, этим завершается и наш учебный курс. В последней лекции будет рассмотрен некоторый заключительный проект.

В этой заключительной лекции новый материал появляться не будет, не будет и традиционных вопросов в конце лекции. Лекция особенная - она посвящена описанию финального проекта, в котором объединены многие, надеюсь, уже хорошо знакомые элементы.

В финальном проекте создается семейство классов, описывающих геометрические фигуры. Проектирование начинается с абстрактного класса поведения, который описывает общие свойства и методы, характерные для всех фигур семейства. Затем, используя наследование, создаются классы конкретных геометрических фигур, начиная с простейших, таких, как круги и прямоугольники, до составных, таких, как класс Person. Мы добавим в наш проект динамические структуры данных, такие, как список с курсором, для хранения в нем фигур семейства. Наконец, мы создадим интерфейс, включающий меню с десятками команд и панель с инструментальными кнопками. Интерфейс позволяет конечному пользователю выполнять различные действия над геометрическими фигурами - создавать, рисовать их на форме, перемещать их с помощью команд и перетаскивать их мышью, менять их размеры и цвет, сохранять в списке и удалять из списка, отображать все фигуры списка или очистить его полностью.

Проект может служить образцом полноценного Windows-приложения, примером проектирования в классах с демонстрацией преимуществ, предоставляемых наследованием. Закончим на этом рекламную часть и приступим к делу. Хочу предупредить, вас ждут программные тексты, почти без всяких комментариев. Все нужные комментарии были даны в предыдущих лекциях. С моей точки зрения, наиболее интересная часть программистских книжек - это та, в которой приводится программный код. И значит, эта глава самая интересная.