Результат работы метода DrawEllipse

Рис. Результат работы метода DrawPolygon.

Рис. Результат работы программы с методом DrawRectangles.

Рис. Задание на метод DrawRectangle

Рис. Результат работы программы.

Рис. Задание на метод DrawLines.

Рис. Задание.

Рис. Результат работы программы.

Рис. Результат работы программы.

Рис. Результат работы программы.

Рис. Вывод данных через контекст устройства

Если приложение получает или создает контекст для устройства отображения, такой контекст называется контекстом отображения (display context). Поэтому когда, например, приложение получает контекст для отображения в одном из своих окон, такой контекст называется контекстом отображения. Если же ему требуется выполнять операцию вывода для устройства (для принтера или для экрана дисплея), приложение должно получить или создать контекст устройства (device context).

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

Класс Graphics

Для того чтобы приложение могло что-нибудь нарисовать в окне, оно должно, прежде всего, получить или создать для этого окна объект класса Graphics. Далее, пользуясь свойствами и методами этого объекта, приложение может рисовать в окне различные фигуры или текстовые строки.

Пример. Создадим приложение, состоящее из формы с белым фоном и возможностью рисования на ней с помощью пера.

Идея будет состоять в следующем. Для того чтобы иметь возможность рисования мы будем отслеживать два события. Событие нажатия на клавишу мыши(mouseDown) и события отпускания клавиши мыши(mouseUp). Отслеживание будет производиться при помощи переменное типа bool. Если кнопка мыши нажата, то переменная становитcя true, если клавиша отпущена, то false. Чтобы отследить перемещение мыши будем использовать событие mouseMove. Собственно большая часть программы будет сосредоточена в обработчике этого события. Результат работ программы представлен на рис.

Рассмотрим более подробно текст программы. Нам нужно сделать так, чтобы пользователь мог рисовать в окне при нажатой левой клавише мыши. Текущее состояние мыши будет храниться в поле Draw типа bool. Создаем три указанных выше обработчика событий мыши.

private void Form1_MouseUp(object sender, MouseEventArgs e)

{

draw = false;

}

private void Form1_MouseDown(object sender, MouseEventArgs e)

{

draw = true;

}

private void Form1_MouseMove(object sender, MouseEventArgs e)

{

if (draw)

{

Graphics g = Graphics.FromHwnd(this.Handle);

SolidBrush myBrush = new SolidBrush(Color.Red);

g.FillRectangle(myBrush, e.X, e.Y, 1,1);

}

}

Когда пользователь нажимает левую клавишу мыши, управление передается обработчику событий Form1_MouseDown. Этот обработчик записывает в поле Draw значение true, отмечая таким способом тот факт, что пользователь приступил к процедуре рисования.

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

Обработчик события Form1_MouseMove будет получать управление при всяком перемещении курсора мыши, причем свойства e.X и e.Y будут содержать новые координаты курсора.

Мы воспользуемся этим обстоятельством, нарисовав в месте нового расположения курсора квадрат, с шириной стороны в один пиксел. На экране такой квадрат будет выглядеть как точка. Рисование должно выполняться только в том случае, если в поле Draw хранится значение true.

Прежде чем мы сможем что-нибудь нарисовать в окне приложения, необходимо получить для этого окна объект класса Graphics. Каждое окно имеет свой идентификатор (handle). Зная идентификатор окна, можно легко получить связанный с этим окном контекст отображения.

Приложения Microsoft.NET Framework могут получить идентификатор формы или любого другого элемента управления при помощи свойства Handle. В частности, наше приложение получает идентификатор окна формы Form1 с помощью свойства this.Handle.

Зная идентификатор окна, с помощью метода Graphics.FromHwnd можно получить нужный объект класса Graphics:

Graphics g = Graphics.FromHwnd(this.Handle);

Для того чтобы рисовать, создадим кисть как объект класса SolidBrush:

SolidBrush redBrush = new SolidBrush(Color.Red);

С помощью этой кисти можно рисовать замкнутые геометрические фигуры, закрашенные заданным цветом. Через единственный параметр мы передаем конструктору класса SolidBrush цвет кисти Color.Red. Таким образом, мы будем рисовать кистью красного цвета.

В классе Graphics имеется множество различных методов, предназначенных для рисования самых разных геометрических фигур, таких как линии, прямоугольники, овалы и окружности, многоугольники, кривые Безье и т.д.

Но классе нет, так это метода, с помощью которого можно было бы нарисовать одну единственную точку. Однако, что вместо точки мы можем нарисовать закрашенный квадрат с шириной стороны, равным 1 пикселу. Эта задача выполняется при помощи метода FillRectangle:

g.FillRectangle(redBrush, e.X, e.Y, 1, 1);

Обратите внимание на то, что метод FillRectangle вызывается для объекта g класса Graphics, созданного нами для окна формы Form1. Поэтому квадрат будет нарисован в окне этой формы.

В качестве первого параметра методу FillRectangle передается кисть redBrush, которую нужно использовать для рисования. Кисть нужна и для других методов класса Graphics, предназначенных для рисования геометрических фигур. Второй и третий параметры метода FillRectangle задают координаты, в которых будет нарисован квадрат.

Начало системы координат при этом находится в левом верхнем углу окна, для которого был получен объект Graphics. В нашем случае это левый верхний угол внутренней области окна формы Form1. Ось X в этой системе координат, принятой по умолчанию, направлена слева направо, а ось Y — сверху вниз. Последние два параметра метода FillRectangle задают, соответственно, ширину и высоту прямоугольника.

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

Событие Paint

Если изменить размеры окна предыдущего изображения часть рисунка пропадает. Аналогичная неприятность происходит и в том случае, когда окно приложения перекрывается окном другого приложения. Дело в том, что в приложении не реализована техника рисования в окне, применяемая во всех стандартных приложениях Microsoft Windows. По своей логике способ рисования программ Microsoft Windows в корне отличается от способа, к которому привыкли разработчики, создававшие программы для ОС MS-DOS.

Известно, что приложения Microsoft Windows не могут выводить текст или графику ни с помощью стандартных функций библиотеки компилятора, например таких, как printf, cprintf или putc. Не помогут и прерывания BIOS, так как приложениям Microsoft Windows запрещено их использовать (во всяком случае, для вывода на экран). Все эти функции ориентированы на консольный вывод в одно-единственное окно, предоставленное в полное распоряжение программе MS-DOS.

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

Способ, которым приложение Microsoft Windows выводит что-либо в свои окна, коренным образом отличается от способа, используемого в программах MS-DOS.

Программа MS-DOS формирует изображение на экране «рассредоточенным» образом, то есть в любом месте программы могут вызываться функции, которые выводят что-либо на экран. Например, сразу после запуска программа может нарисовать на экране диалоговую панель, а затем в любой момент времени и, что самое главное, из любого места программы модифицировать ее.

Приложения Microsoft Windows также могут выводить в созданные ими окна текст или графические изображения в любой момент времени и из любого места. Именно так поступает наше приложение. Однако обычно разработчики поступают по-другому.

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

Для наглядной демонстрации методики обработки события Paint мы подготовим простейшее приложение PaintApp, рисующее в своем окне текстовую строку и геометрические фигуры.

Пример. Создадим приложение, которое выводило бы на экран форму следующего вида (рис.)

Для того чтобы заголовок окна поменял название при загрузке окна, необходимо поменять для него свойство Text в обработчике события Load. При этом стоит отметить, что событие Load является событием форму по умолчанию и для перехода к его обработчику достаточно дважды кликнуть мышью на форму.

private void Form1_Load(object sender, EventArgs e)

{

this.Text = "Событие Paint";

}

Рассмотрим обработчик события Paint.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

string text = "Событие Paint";

g.Clear(Color.White);

g.DrawString(text, new Font("Helvetica", 15),Brushes.Red, 50, 0);

g.DrawRectangle(new Pen(Brushes.Blue, 2), 10, 30, 200, 100);

g.DrawEllipse(new Pen(Brushes.Green, 2), 10, 30, 200, 100);

}

Обработчику Form1_Paint передаются два параметра.

Через первый параметр передается ссылка на объект, вызвавший событие. В нашем случае это будет ссылка на форму Form1. Что же касается второго параметра, то через него передается ссылка на объект класса PaintEventArgs. Этот объект имеет два свойства, доступных только для чтения — Graphics и ClipRectangle.

Класс Graphics уже знаком — он представляет собой контекст отображения, необходимый для рисования текста и геометрических фигур. Обработчик события Paint получает контекст отображения через свои параметры, поэтому программисту не нужно определять его специальным образом.

Через свойство ClipRectangle передаются границы области, которую должен перерисовать обработчик события Paint. Эти границы передаются в виде объекта класса Rectangle. Свойства этого класса Left, Right, Width и Height, наряду с другими свойствами, позволяют определить расположение и размеры области.

Заметим, что в простейших случаях обработчик события Paint может игнорировать свойство ClipRectangle, перерисовывая содержимое окна полностью. Однако процесс перерисовки содержимого окна можно заметно ускорить, если перерисовывать не все окно, а только область, описанную свойством ClipRectangle. Ускорение будет особенно заметным, если в окне нарисовано много текста и геометрических фигур.

Рассмотрим содержание обработчика события Paint. Здесь в теле обработчика Form1_Paint мы определили локальную переменную g класса Graphics, предназначенную для хранения контекста отображения. Эта переменная инициализируется при помощи значения, полученного из свойства Graphics первого параметра обработчика Form1_Paint:

Graphics g = e.Graphics;

Получив контекст отображения, наш обработчик события Paint может рисовать в соответствующем окне все, что угодно.

Вначале мы закрашиваем окно белым цветом, вызывая для этого метод Clear, определенный в классе Graphics:

g.Clear(Color.White);

Таким способом мы можем закрасить фон, цвет которого задан для формы в свойстве BackColor.

Далее мы вызываем методы DrawString, DrawRectangle и DrawEllipse, также определенные в классе Graphics:

g.DrawString(text, new Font("Helvetica", 15),Brushes.Red, 50, 0);

g.DrawRectangle(new Pen(Brushes.Blue, 2), 10, 30, 200, 100);

g.DrawEllipse(new Pen(Brushes.Green, 2), 10, 30, 200, 100);

Тема Методы и свойства класса Graphics. Рисование геометрических фигур

Рисование линии (DrawLine)

За рисование линий в C# отвечает метод DrawLine. Он рисует линию, соединяющую две точки с заданными координатами. Указанный метод может быть перегружен. Ниже (на слайде) указаны варианты перегрузки этого метода. Рассмотрим отдельно каждый вариант перегрузки см. слайд.

public void DrawLine(Pen, int, int, int, int);
public void DrawLine(Pen, float, float, float, float);

public void DrawLine(Pen, Point, Point);
public void DrawLine(Pen, PointF PointF);

Первый параметр во всех вариантах перегрузки задает инструмент для рисования линии — перо. Перья создаются как объекты класса Pen. Программно это будет выглядеть следующим образом:

Pen myPen = new Pen(Brushes.Aqua,5);

Здесь мы создали перо цвета Aqua толщиной 5 пикселов.

Остальные параметры перегруженных методов DrawLine задают координаты соединяемых точек. Эти координаты могут быть заданы как объекты класса Point и PointF, а также в виде целых чисел и чисел с плавающей десятичной точкой.

Для первых двух вариантов первая пара определяет координаты первой точки по горизонтальной и вертикальной оси, а вторая — координаты второй точки по этим же осям. Разница между первым и вторым методом заключается в использовании координат различных типов (целочисленных int и с плавающей десятичной точкой float). Для варианта целых чисел вызов методов будет выглядеть следующим образом.

g.DrawLine(myPen,10,100,200,100);

Для варианта с классом Point вызов метода будет выглядеть следующим образом.

Point myPoint1 = new Point(100, 100);

Point myPoint2 = new Point(200,100);

g.DrawLine((new Pen(Brushes.Red, 5)), myPoint1, myPoint2);

В классах Point и PointF определены свойства X и Y, задающие, соответственно, координаты точки по горизонтальной и вертикальной оси. При этом в классе Point эти свойства имеют целочисленные значения, а в классе PointF — значения с плавающей десятичной точкой.

Объединив описанные строки получим обработчик события Form1_Paint.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

Pen myPen = new Pen(Brushes.Aqua,5);

g.DrawLine(myPen,10,100,100,100);

Point myPoint1 = new Point(100, 100);

Point myPoint2 = new Point(200,100);

g.DrawLine((new Pen(Brushes.Red, 5)), myPoint1, myPoint2);

}

Результат работы программы представлен ниже.

Задание. Напасать программу, которая бы выводила на экран картинку следующего вида см. слайд (рис). Для реализации использовать цикл и метод:

public void DrawLine(Pen, int, int, int, int);

Набор линий (DrawLines)

В C# существует и другой способ нарисовать несколько линий. Этого можно достигнуть, вызвав один раз метод DrawLines, который позволит нарисовать сразу несколько прямых линий, соединенных между собой. По своей сути метод DrawLines позволяет соединить между собой несколько точек. Координаты этих точек по горизонтальной и вертикальной оси передаются методу через массив класса Point или PointF. Ниже представлены перегрузки метода DrawLines.

public void DrawLines(Pen, Point[]);
public void DrawLines(Pen, PointF[];

Продемонстрируем работу метода DrawLines. Предположим, что нам необходимо нарисовать изображение следующего вида(рис.) см. слайд.

Для решения задачи объявим в классе Form1 этого приложения мы создаем кисть pen для рисования линий и объявляем массив mypen.

Pen mypen = new Pen(Color.Red, 2);

Point[] points = new Point[50];

Далее в конструкторе формы инициализируем массив точек points, которые нужно соединить линиями.

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

{

int x;

if (i % 2 == 0)

{

x = 10;

}

else

{

x = 400;

}

points[i] = new Point(x, 10 * i);

}

Координаты точек по горизонтальной оси зависят от того, является ли значение переменной цикла i четным или нечетным.

Обработчик события Form1_Paint будет иметь вид (см. слайд).

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

g.SmoothingMode = SmoothingMode.HighQuality;

g.DrawLines(mypen,points);

}

Результат работы программы приведен на (рис)(см. слайд).

В приведенном коде появилась новая неизвестная строчка.

g.SmoothingMode = SmoothingMode.HighQuality;

Если сравнить два рисунка, то можно заметить, что линии на втором рисунке гладкие и не содержат ступенек (см. слайд). Это позволил сделать один из параметров контекста отображения, а именно параметр SmoothingMode. Этот параметр задает режим сглаживания при отображении линий. Стоит обратить внимание, что для его использования необходимо добавить пространство имен System.Drawing.Drawing2D в самом начале файла. Для чего используем ключевое слово using.(см. слайд)

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Linq;

using System.Text;

using System.Windows.Forms;

Стоит отметить, что использование сглаживания повышает качество изображения, однако приводит к уменьшению скорости рисования.

Рисование прямоугольника(DrawRectangle)

Метод DrawRectangle позволяет рисовать прямоугольники, заданные координатой верхнего левого угла, а также шириной и высотой. В библиотеке классов.NET Frameworks имеется три перегруженных варианта этого метода см. слайд.

public void DrawRectangle(Pen, Rectangle);
public void DrawRectangle(Pen, int, int, int, int);
public void DrawRectangle(Pen, float, float, float, float);

В качестве первого параметра этим методам передается уже известное нам перо класса Pen. Остальные параметры задают расположение и размеры прямоугольника.

Класс Rectangle используется для описания расположения и размеров прямоугольной области. Интересующая нас сигнатура конструктора имеет вид.

Rectangle(X,Y, Width, Height)

Свойства X и Y этого класса задают координаты верхнего левого угла прямоугольной области, соответственно, по горизонтальной и вертикальной оси координат. Свойства Width и Height, хранят ширину и высоту прямоугольной области.

Варианты метода DrawRectangle с пятью параметрами позволяют задавать расположение и размеры прямоугольника в виде целых чисел, а также в виде числе с плавающей десятичной точкой. Второй и третий параметр задает расположение верхнего левого угла по горизонтальной и вертикальной оси координат, соответственно, а четвертый и пятый — ширину и высоту прямоугольника.

Проверим работу первых двух методов на примере см. слайд (рис.)

Для решения задачи необходимо создать инструмент для рисования.

Pen myPen = new Pen(Brushes.Blue, 2);

В данном случае это перо синего цвета толщиной в 2 пикселя и объект класса Rectangle.

Rectangle myRectangle = new Rectangle(10,10, 200,200);

Далее применим описанные выше методы.

g.DrawRectangle(myPen, myRectangle);

g.DrawRectangle(myPen, 20,20, 180, 180);

Полный текст обработчика события Form1_Paint приведен ниже см. слайд.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

Pen myPen = new Pen(Brushes.Blue, 2);

g.Clear(Color.White);

Rectangle myRectangle = new Rectangle(10,10, 200,200);

g.DrawRectangle(myPen, myRectangle);

g.DrawRectangle(myPen, 20,20, 180, 180);

}

Набор прямоугольников (DrawRectangles)

Если возникает необходимость нарисовать сразу несколько прямоугольников целесообразно использовать метод DrawRectangles. Существует два перегруженных варианта этого метода:

public void DrawRectangles(Pen, Rectangle[]);
public void DrawRectangles(Pen, RectangleF[]);

Первый из этих методов получает в качестве второго параметра ссылку на массив объектов класса Rectangle, описывающих размеры и расположение прямоугольных областей. Второй метод использует для этого объекты класса RectangleF. Их различие состоит в том, что свойства X, Y, Width и Height второго задают расположение и размеры прямоугольника в виде чисел с плавающей десятичной точкой.

Для демонстрации работы метода решим задачу из предыдущего пункта.

Для этого в классе Form1 приложения определим перо myPen и массив прямоугольников myRects:

Rectangle[] myRects =

{

new Rectangle(10, 10, 200, 200),

new Rectangle(20, 20, 180, 180),

};

Далее вызываем метод DrawRectangles аргументами которого будут перо myPen и массив прямоугольников myRects.

g.DrawRectangles(myPen, myRects);

Полностью код обработчика события Form1_Paint имеет вид.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

Pen myPen = new Pen(Color.Blue, 2);

Rectangle[] myRects =

{

new Rectangle(10, 10, 200, 200),

new Rectangle(20, 20, 180, 180),

};

g.DrawRectangles(myPen, myRects);

}

Результат работы программы приведен на рис.

Рисование многоугольника (DrawPolygon)

Метод DrawPoligon предназначен для рисования многоугольников. Существуюет две перегруженные версии этого метода (см.слайд).

public void DrawPolygon(Pen, Point[]);
public void DrawPolygon(Pen, PointF[]);

Аргументами метода является в перо Pen и массив точек класса Point.

Продемонстрируем работу метода на примере ромба.

Массив с координатами вершин ромба будет иметь вид.

Point [] myPoint =

{

new Point(140, 10),

new Point(200, 100),

new Point(140, 210),

new Point(80, 100),

};

Вызов метода DrawPolygon выглядит следующим образом.

g.DrawPolygon(myPen,myPoint);

Полностью текст обработчика события Form1_Paint имеет вид.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

Pen myPen = new Pen(Color.Blue, 2);

Point [] myPoint =

{

new Point(140, 10),

new Point(200, 100),

new Point(140, 210),

new Point(80, 100),

};

g.DrawPolygon(myPen,myPoint);

}

Результат работы программы представлен на рис.

Рисование эллипса(DrawEllipse)

Метод DrawEllipse позволяет нарисовать эллипс, который вписан в прямоугольную область. Размер этой области передается методу в качестве параметров. В связи с этим рисование эллипса похоже на рисование прямоугольника, а и соответственно и параметры перегруженных методов DrawEllipse идентичны с параметрами метода DrawRectangle. Возможные варианты перегрузки методов представлены ниже (см. слайд).

public void DrawEllipse(Pen, Rectangle);
public void DrawEllipse(Pen, RectangleF);
public void DrawEllipse(Pen, int, int, int, int);
public void DrawEllipse(Pen, float, float, float, float);

Указанные методы, как и в случае DrawRectangle, отличаются только способом, при помощи которого описывается расположение и размеры прямоугольной области, в которую вписан эллипс.

Нарисуем эллипс при помощи первого перегруженного метода. Код обработчика события Form1_Paint имеет вид.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

Pen myPen = new Pen(Color.Blue, 2);

Rectangle myRect = new Rectangle(10, 10, 200, 100);

g.DrawEllipse(myPen, myRect);

}

Результат работы метода представлен на рис.

Рисование сегмента эллипса (DrawArc)

Для рисования сегмента эллипса предназначен метод DrawArc. Аналогично эллипсу, сегмент задается при помощи координат прямоугольной области, в которую вписан эллипс, а также двух углов, которые отсчитываются в направлении против часовой стрелки (см слайд) рис.

Рис. Принцип построения сегмента эллипса

Первый угол Angle1 задает расположение одного конца сегмента, а второй Angle2 — расположение другого конца сегмента.

Для рисования сегмента эллипса в C# предусмотрено четыре перегруженных варианта метода DrawArc:

public void DrawArc(Pen, Rectangle, float, float);
public void DrawArc(Pen, RectangleF, float, float);
public void DrawArc(Pen, int, int, int, int, int, int);
public void DrawArc(Pen, float, float, float, float, float, float);

Первый параметр метода DrawArc традиционно определяет перо, с помощью которой будет нарисован сегмент. Последние два параметра задают углы Angle1 и Angle2 в соответствии с рис. Расположение и размеры прямоугольной области передаются методу DrawArc также, как это делается для рассмотренного выше метода DrawEllipse.

Применим указанный метод для рисования сегмента эллипса с углами 90 и 180 соответственно.

Вызов метода будет выглядеть следующим образом.

g.DrawArc(myPen, myRect,90,180);

Код обработчика события Form1_Paint имеет вид (см слайд).

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

Pen myPen = new Pen(Color.Blue, 2);

Rectangle myRect = new Rectangle(10, 10, 200, 100);

g.DrawArc(myPen, myRect,90,180);

}

Результат работы программы представлен на рис.

Рис. Результат работы метода DrawArc

Рисование замкнутого сегмента эллипса(DrawPie)

Для рисования замкнутого сегмента эллипса используется метод DrawPie. Имеется 4 перегруженных варианта этого метода:

public void DrawPie(Pen, Rectangle, float, float);
public void DrawPie(Pen, RectangleF, float, float);
public void DrawPie(Pen, int, int, int, int, int, int);
public void DrawPie(Pen, float, float, float, float, float, float);

В качестве первого параметра методу нужно передать перо для рисования. Последние два параметра определяют углы, ограничивающие сегмент эллипса. Эти углы используются таким же образом, как и при рисовании незамкнутого сегмента эллипса методом DrawArc. Остальные параметры задают расположение и размеры прямоугольника, в который вписывается сегмент эллипса.

Решим предыдущую задачу при помощи метода DrawPie. Вызов метода будет выглядеть следующим образом.

g.DrawPie(myPen, myRect, 90, 180);

Код обработчика события Form1_Paint имеет вид (см слайд).

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

Pen myPen = new Pen(Color.Blue, 2);

Rectangle myRect = new Rectangle(10, 10, 200, 100);

g.DrawPie(myPen, myRect, 90, 180);

}

Результат работы метода представлен на рис.

Рис. Результат работы метода DrawPie.

Рисование кривых Безье (DrawBezier и DrawBeziers)

Кривая Безье, представляющая собой одну из разновидностей сплайна, задается четырьмя точками. Две из них — начальная и конечная, а две другие — управляющие. Кривая Безье проходит через начальную и конечную точки, а управляющие точки задают изгибы кривой линии. Кривые Безье часто используют при работе в графических редакторах. Для рисования кривых Безье в C# имеются два группы перегруженных методов DrawBezier и DrawBeziers (см. слайд). Различие этих групп заключается в способе представления координат точек. В группе DrawBezier координаты точек являются аргументами методов в явном виде или в виде объектов классов Point и PointF, а в группе DrawBeziers аргументами метода являются массивы объектов класса Point и PointF.

public void DrawBezier(Pen, Point, Point, Point, Point);
public void DrawBezier(Pen, PointF, PointF, PointF, PointF);
public void DrawBezier(Pen, float, float, float, float, float, float, float, float);

public void DrawBeziers(Pen, Point[]);
public void DrawBeziers(Pen, PointF[]);

Продемонстрируем работу двух групп перегруженных методов на примере.

Для группы DrawBezier код будет выглядеть следующим образом. Задаем объекты класса Point.

Point point1 = new Point(10, 80);

Point point2 = new Point(50, 50);

Point point3 = new Point(110, 150);

Point point4 = new Point(190, 80);

Вызываем метод DrawBezier.

g.DrawBezier(myPen, point1,point2,point3,point4);

Для группы DrawBeziers создадим массив точек класса Point.

Point [] myPoint =

{

new Point(10, 100),

new Point(50, 90),

new Point(110, 190),

new Point(190, 60)

};

Вызов метода DrawBeziers будет выглядеть следующим образом.

g.DrawBeziers(new Pen(Color.Red),myPoint);

Код обработчика события Form1_Paint имеет вид (см слайд).

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

Pen myPen = new Pen(Color.Blue, 2);

Point point1 = new Point(10, 80);

Point point2 = new Point(50, 50);

Point point3 = new Point(110, 150);

Point point4 = new Point(190, 80);

g.DrawBezier(myPen, point1,point2,point3,point4);

Point [] myPoint =

{

new Point(10, 100),

new Point(50, 90),

new Point(110, 190),

new Point(190, 60)

};

g.DrawBeziers(new Pen(Color.Red),myPoint);

}

Результат работы методов представлен на рис.

Рис. Результат работы методов DrawBezier и DrawBeziers

Рисование канонических сплайнов (DrawCurve и DrawClosedCurve)

В отличие от только что рассмотренных кривых линий Безье, линии канонического или обычного сплайна проходит через все заданные точки. Для рисования обычных сплайнов предусмотрены группы перегруженных методов методы DrawCurve и DrawClosedCurve. Первая группа методов рисует незамкнутую кривую линию (открытый сплайн), а второй — замкнутую (закрытый сплайн).

В простейшем случае методам передается перо и массив соединяемых точек.

public void DrawCurve(Pen, Point[]);
public void DrawCurve(Pen, PointF[]);

public void DrawCurveClosed(Pen, Point[]);
public void DrawCurveClosed(Pen, PointF[]);

Рассмотрим работу методов DrawCurve и DrawCurveClosed на примере предыдущей задачи.

Вызов метода DrawCurve выглядит следующим образом.

g.DrawCurve(myPen,myPoint);

Результат работы метода представлен на рис.

Рис. Работа метода DrawCurve

Вызов метода DrawCurveClosed имеет вид.

g.DrawClosedCurve(myPen, myPoint);

Результат работы метода DrawClosedCurve представлен на рис.

Рис. Результат работы метода DrawClosedCurve

Обработчик события Form1_Paint имеет вид.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

Pen myPen = new Pen(Color.Blue,2);

g.Clear(Color.White);

Point[] myPoint =

{

new Point(10, 100),

new Point(50, 90),

new Point(110, 190),

new Point(190, 60)

};

g.DrawCurve(myPen,myPoint);

g.DrawClosedCurve(myPen, myPoint);

}

Существуют версии методов, позволяющие дополнительно задать так называемую жесткость сплайна. Жесткость задается в виде третьего дополнительного параметра:

public void DrawCurve(Pen, Point[], float);
public void DrawCurve(Pen, PointF[], float);

По умолчанию значение жесткости равно 0,5. При увеличении этого параметра увеличиваются изгибы кривой линии. При жесткости большей 1 или меньшей 0 кривая может превратиться в петлю.

Решим предыдущую задачу при помощи указанных методов, жесткость равна 1,5 и 0.

Рис. Результат работы DrawCurve при жесткости 1.5 и 0

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

По умолчанию используется режим Alternate. Чтобы определить внутренние части замкнутых фигур в режиме чередования, рисуется линия из произвольной начальной точки контура к некоторой точке, которая явно расположена вне контура. Если линия пересекает нечетное число сегментов контура, начальная точка находится внутри замкнутой области и, следовательно, является частью области заполнения или отсечения. Четное число пересечений означает, что точка не находится в области, которая должна быть заполнена или отсечена. Незамкнутая фигура заполняется или отсекается путем использования линии, соединяющей последнюю и первую точки контура.

Режим Winding учитывает направление сегментов контура на каждом пересечении. В этом режиме добавляется единица для каждого пересечения по часовой стрелке и вычитается единица для каждого пересечения против часовой стрелки. Если результат отличен от нуля, точка считается расположенной внутри области заполнения или отсечения. Нулевой результат означает нахождение точки вне области заполнения или отсечения.

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

public void DrawClosedCurve(Pen, Point[], float, FillMode);
public void DrawClosedCurve(Pen, PointF[], float, FillMode);

Рисование закрашенных фигур.

В классе Graphics определен ряд методов, предназначенных для рисования закрашенных фигур. Имена некоторых из этих методов, имеющих префикс Fill, мы перечислили в табл. 10‑2.

FillRectangle - рисование закрашенного прямоугольника;

FillRectangles – рисование множества закрашенных прямоугольников;

FillPolygon - рисование закрашенного многоугольника;

FillEllipse - рисование закрашенного сегмента эллипса;

FillPie - рисование закрашенного сегмента эллипса

FillClosedCurve Рисование закрашенного сплайна

FillRegion Рисование закрашенной области типа Region

Есть два отличия методов с префиксом Fill от одноименных методов с префиксом Draw. Прежде всего, методы с префиксом Fill рисуют закрашенные фигуры, а методы с префиксом Draw — не закрашенные. Кроме этого, в качестве первого параметра методам с префиксом Fill передается не перо класса Pen, а кисть класса Brush.

Рассмотрим пример рисования фигуры при помощи метода FillRegion.

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

Метод FillRegion заполняет внутреннюю часть объекта заданного при помощи объекта Region.

Для решения задачи создадим инструмент для рисования SolidBrush красного цвета.

SolidBrush myBrush = new SolidBrush(Color.Red);

Зададим область заливки в виде прямоугольника при помощи объекта класса Rectangle.

Rectangle myRect = new Rectangle(10,10, 200,200);

Вызов метода FillRegion будет выглядеть следующим образом.

g.FillRegion(myBrush,new Region(myRect));

Код обработчика события Form1_Paint имеет вид (см слайд).

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

SolidBrush myBrush = new SolidBrush(Color.Red);

Rectangle myRect = new Rectangle(10,10, 200,200);

g.FillRegion(myBrush,new Region(myRect));

}

Результат работы программы представлен на рис.

Рис. Работа метода FillRegion

Тема. Инструменты для рисования

На данный момент при рисовании стандартных фигур были использованы два инструмента для рисования: SolidBrush и Pen. В данном разделе будут описаны другие возможные инструменты для рисования и заливки различных фигур.

Стоит напомнить, что для использование некоторых возможностей класса Graphics необходимо подключить пространство имен System.Drawing.Drawing2D.

Инструмент для рисования перо (Pen) и его свойства

Перья используются для рисования линий и простейших геометрических фигур и создаются как объекты класса Pen.

Существуют несколько видов перегруженных конструкторов.

public Pen(Color);
public Pen(Color, float);
public Pen(Brush);
public Pen(Brush, float);

Первый вариант конструктора создает перо заданного цвета. Цвет задается при помощи объекта класса Color, расположенного в пространстве имен System.Drawing.Color.

Pen myPen = Pen(Color.Red);

Второй конструктор позволяет дополнительно задать толщину пера при помощи аргумента типа float, в нашем случае толщина линии задается размером 4 пикселя.

Pen myPen = Pen(Color.Red, 4);

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

Pen myPen = Pen(Brushes.Red, 4);

После того как перо создано, программа может определить его атрибуты при помощи свойств класса Pen. Рассмотрим отдельно свойства класса Pen.

Свойство PenAlignment пример использования приведен ниже. Это свойство определяет, каким образом объект Pen рисует замкнутые кривые и многоугольники. Перечислением PenAlignment задаются пять значений: Center; Inset; Right; Left; Outset. Однако только два значения — Center и Inset изменяют внешний вид рисуемой линии.

Значение Center устанавливается по умолчанию для этого свойства, и им задается центрирование ширины пера по контуру кривой или многоугольника. Значение Inset этого свойства соответствует размещению пера по всей ширине внутри границы кривой или многоугольника. Три другие значения, Right, Left и Outset задают центрированное перо.

Перо Pen, для которого выравнивание установлено равным Inset, выдает недостоверные результаты, иногда рисуя в позиции вставки, а иногда — в центрированном положении. К тому же, вложенное перо невозможно использовать для рисования составных линий, и оно не позволяет рисовать пунктирные линии с оконечными элементами Triangle.

myPen.Alignment = PenAlignment.Center;

Свойство Brush. Получает или задает объект Brush, определяющий атрибуты объекта Pen. Назначение этого свойства позволяет перу рисовать заполненные линии и кривые. Оно переопределяет свойство Color объекта Pen.

myPen.Brush = Brushes.Blue;

Рис. Результат работы свойства Brush

Свойство Color. Получает или задает цвет объекта Pen. Изменим цвет пера на красный при помощи этого свойства.

myPen.Color = Color.Red;

Рис. Результат работы свойства Color

Свойство CompoundArray. Получает или задает массив значений, определяющий составное перо. Составное перо рисует составную линию, состоящую из параллельных линий и разделяющих их промежутков.

Составная линия состоит из сменяющих друг друга параллельных линий и промежутков различной ширины. Значения массива задают начальные точки компонентов составной линии относительно ширины пера. Первое значение массива задает начало первого компонента (линии) по ширине пера и в долях от нее. Второе значение массива задает начало следующего компонента (пробела) по ширине пера и в долях от нее. Последнее значение массива задает окончание последнего компонента.

Предположим, что нужно создать перо, рисующее две параллельные линии. Первую линию толщиной 20% от ширины пера, пробел, разделяющий линии, — 50% от ширины пера, а вторую линию — 30% от ширины пера.

Для этого необходимо создать массив следующего вида.

float[] d = { 0.0F, 0.2F, 0.7F, 1F };

И присвоить его значение свойству CompoundArray.

myPen.CompoundArray = d;

В результате получим следующий обработчик события Form1_Paint.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

Pen myPen = new Pen(Color.Black,10);

myPen.Color = Color.Red;

float[] d = { 0.0F, 0.2F, 0.7F, 1F };

myPen.CompoundArray = d;

g.DrawLine(myPen,10,50,200,50);

}

Результат работы свойства представлен на рис.

Рис. Результат работы свойства CompoundArray

Свойство Width. Получает или устанавливает ширину пера Pen, в единицах объекта Graphics, используемого для рисования.

myPen.Width = 5;

Свойство EndCap. Задает окончание линий, нарисованных при помощи объекта Pen. Этому свойству присваиваются значения из перечисления LineCap.

myPen.EndCap = LineCap.ArrowAnchor;

Это перечисление содержит следующие значения.

Flat - задает плоское завершение отрезка.

Square - задает квадратное завершение отрезка.

Round - задает круглое завершение отрезка.

Triangle - задает треугольное завершение отрезка.

NoAnchor - не задает маркер.

SquareAnchor - задает квадратный маркер завершения отрезка.

RoundAnchor - задает круглый маркер.

DiamondAnchor - задает маркер в форме ромба.

ArrowAnchor - задает маркер в форме стрелки.

Свойство StartCap. Задает начало линий, нарисованных при помощи объекта Pen. Этому свойству присваиваются значения из перечисления LineCap

myPen.StartCap = LineCap.DiamondAnchor;

Свойство DashCap. Получает или задает стиль окончания пунктиров, ограничивающих пунктирные линии, нарисованные при помощи объекта Pen. Свойству DashCap присваиваются одно из значений перечисления DashCap. Это перечисление содержит следующие значения для начала и окончания штриха: Flat(квадратное); Round(круглое); Triangle(треугольное).

Свойство DashOffset. Получает или задает расстояние от начала линии до начала штрихового шаблона.

Свойство DashPattern. Получает или задает массив настраиваемых штрихов и промежутков. Элементы массива dashArray задают длину всех штрихов и промежутков штрихового шаблона. Первый элемент задает длину штриха, второй — длину промежутка, третий — длину следующего штриха и так далее. Длина каждого штриха и промежутка штрихового шаблона вычисляется исходя из значения элемента массива и ширины объекта Pen.

float [] DashArray = {4.0F, 2.0F, 1.0F, 3.0F};

myPen.DashPattern = DashArray;

Свойство DashStyle. Получает или задает стиль, используемый для пунктирных линий, нарисованных при помощи объекта Pen. Значениями свойства является перечисление DashStyle, представляющее стиль, используемый для пунктирных линий, нарисованных при помощи объекта Pen. Это перечисление содержит следующие значения.

Solid - Задает сплошную линию.

Dash - Задает линию, состоящую из штрихов.

Dot - Задает линию, состоящую из точек.

DashDot - Задает штрих-пунктирную линию.

DashDotDot - Задает линию, состоящую из повторяющегося шаблона "штрих-две точки".

Custom - Задает пользовательский тип пунктирных линий.

Работа этого свойства выглядит следующим образом.

myPen.DashStyle = DashStyle.DashDotDot;

В результате получим следующий обработчик события Form1_Paint.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

Pen myPen = new Pen(Color.Black);

myPen.Color = Color.Red;

myPen.Width = 5;

myPen.EndCap = LineCap.ArrowAnchor;

myPen.StartCap = LineCap.DiamondAnchor;

g.DrawLine(myPen, 10, 10, 200, 10);

float [] DashArray = {4.0F, 2.0F, 1.0F, 3.0F};

myPen.EndCap = LineCap.Flat;

myPen.StartCap = LineCap.Round;

myPen.DashCap = DashCap.Triangle;

myPen.DashPattern = DashArray;

g.DrawLine(myPen, 10, 20, 200, 20);

myPen.EndCap = LineCap.RoundAnchor;

myPen.StartCap = LineCap.Square;

myPen.DashStyle = DashStyle.DashDotDot;

g.DrawLine(myPen, 10, 30, 200, 30);

myPen.EndCap = LineCap.NoAnchor;

myPen.StartCap = LineCap.NoAnchor;

myPen.DashStyle = DashStyle.Dot;

g.DrawLine(myPen, 10, 40, 200, 40);

}

Рис. Результат работы обработчика события Form1_Paint

Инструмент для рисования кисть (Brush)

Внутренняя область замкнутых геометрических фигур может быть закрашена при помощи кисти. В приложениях Microsoft.NET Frameworks кисти создаются на базе классов, производных от абстрактного класса Brush. Это следующие классы: Brushes; SolidBrush; HatchBrush; TextureBrush; LinearGradientBrush; PathGradientBrush.Рассмотрим отдельно каждый из этих классов.

Кисть SolidBrush

Простейшей из кистей — является кисть SolidBrush, предназначенная для сплошной закраски фигур. Эти кисти создается при помощи конструктора с одним параметром, задающим цвет в виде объекта класса Color.

Вызов конструктора кисти SolidBrush синего цвета выглядит следующим образом.

SolidBrush mySolidBrush = new SolidBrush(Color.Blue);

Код обработчика события Form1_Paint.

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

g.Clear(Color.White);

SolidBrush mySolidBrush = new SolidBrush(Color.Blue);

g.FillRectangle(mySolidBrush, new Rectangle(10,10,100,100));

}

Результатом работы программы будет квадрат синего цвета нарисованный при помощи кисти SolidBrush и метода FillRectangle (рис).

Рис. Результат работы программы.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  




Подборка статей по вашей теме: