| netlib.narod.ru | < Назад | Оглавление | Далее > |
Чаще всего контур визуализируют при помощи одного из методов класса Graphics:
Методы Graphics (выборочно)
| void DrawPath(Pen pen, GraphicsPath path) |
| void FillPath(Brush brush, GraphicsPath path) |
Метод DrawPath рисует заданным пером прямые и кривые, составляющие контур. FillPath заливает внутренние области всех замкнутых фигур, используя заданную кисть. Хотя этот метод закрывает открытые фигуры, чтобы выполнить заливку, он не вносит в контур постоянных изменений. Если в контуре есть пересекающиеся линии, то заливка внутренних областей определяется значением свойства FillPath объекта GraphicsPath. При визуализации все точки контура подвергаются любым преобразованиям, установленным для объекта Graphics.
А теперь посмотрим, как все это работает на практике. Программа Flower рисует цветок при помощи контуров и преобразования.
Flower.cs
//---------------------------------------
// Flower.cs (C) 2001 by Charles Petzold
//---------------------------------------
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
class Flower: PrintableForm
{
public new static void Main()
{
Application.Run(new Flower());
}
public Flower()
{
Text = "Flower";
}
protected override void DoPage(Graphics grfx, Color clr, int cx, int cy)
{
// Рисуем зеленый стебель из нижнего левого угла к центру
grfx.DrawBezier(new Pen(Color.Green, 10),
new Point(0, cy), new Point(0, 3 * cy / 4),
new Point(cx / 4, cy / 4), new Point(cx / 2, cy / 2));
// Устанавливаем преобразование для оставшегося цветка
float fScale = Math.Min(cx, cy) / 2000f;
grfx.TranslateTransform(cx / 2, cy / 2);
grfx.ScaleTransform(fScale, fScale);
// Рисуем красные лепестки
GraphicsPath path = new GraphicsPath();
path.AddBezier(new Point( 0, 0), new Point(125, 125),
new Point(475, 125), new Point(600, 0));
path.AddBezier(new Point(600, 0), new Point(475, -125),
new Point(125, -125), new Point( 0, 0));
for (int i = 0; i < 8; i++)
{
grfx.FillPath(Brushes.Red, path);
grfx.DrawPath(Pens.Black, path);
grfx.RotateTransform(360 / 8);
}
// Рисуем желтый круг в центре
Rectangle rect = new Rectangle(-150, -150, 300, 300);
grfx.FillEllipse(Brushes.Yellow, rect);
grfx.DrawEllipse(Pens.Black, rect);
}
}
Исполнение метода DoPage начинается с рисования изображающей стебель цветка кривой Безье, которая начинается из левого нижнего угла и заканчивается в центре клиентской области (или страницы принтера). Далее программа задает глобальное преобразование, чтобы создать изотропную область для рисования, разбитую на четыре квадранта. Координаты этой области меняются от –1000 до 1000, а начало координат расположено в центре области.
Далее программа должна нарисовать несколько лепестков, и здесь в дело вступает контур. Если бы лепестки были эллиптическими, я просто вызвал бы метод FillEllipse. Но форма лепестка точнее определяется парой кривых Безье, а для заливки полученной фигуры нужен контур. Создав контур, программа восемь раз вызывает методы FillPath и DrawPath. Каждый раз после их вызова RotateTransform изменяет глобальное преобразование объекта Graphics, в результате лепестки располагаются по кругу вокруг центра цветка. Метод DoPage завершается рисованием желтого круга в центре клиентской области.

Уверен, вы помните программу Scribble из главы 8. Тогда я показывал, как сохранить все нарисованные пользователем линии при помощи класса ArrayList. Этот объект напоминает массив, способный динамически изменять свой размер. На самом деле применение объекта ArrayList весьма напоминает сохранение координат в контуре. Замена ArrayList объектом GraphicsPath позволяет существенно упростить программу, которая в этом случае становится даже проще, чем версия из главы 11 (ScribbleWithBitmap), сохраняющая рисунок при помощи скрытого изображения.
ScribbleWithPath.cs
//-------------------------------------------------
// ScribbleWithPath.cs (C) 2001 by Charles Petzold
//-------------------------------------------------
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
class ScribbleWithPath: Form
{
GraphicsPath path;
bool bTracking;
Point ptLast;
public static void Main()
{
Application.Run(new ScribbleWithPath());
}
public ScribbleWithPath()
{
Text = "Scribble with Path";
BackColor = SystemColors.Window;
ForeColor = SystemColors.WindowText;
// Создаем контур
path = new GraphicsPath();
}
protected override void OnMouseDown(MouseEventArgs mea)
{
if (mea.Button != MouseButtons.Left)
return;
ptLast = new Point(mea.X, mea.Y);
bTracking = true;
// Начало фигуры
path.StartFigure();
}
protected override void OnMouseMove(MouseEventArgs mea)
{
if (!bTracking)
return;
Point ptNew = new Point(mea.X, mea.Y);
Graphics grfx = CreateGraphics();
grfx.DrawLine(new Pen(ForeColor), ptLast, ptNew);
grfx.Dispose();
// Добавляем линию
path.AddLine(ptLast, ptNew);
ptLast = ptNew;
}
protected override void OnMouseUp(MouseEventArgs mea)
{
bTracking = false;
}
protected override void OnPaint(PaintEventArgs pea)
{
// Рисуем контур
pea.Graphics.DrawPath(new Pen(ForeColor), path);
}
}
Помимо дополнительной инструкции using, для превращения версии программы Scribble, не сохраняющей пользовательские рисунки, в ScribbleWithPath, нужно определить контур как переменную-поле и добавить всего 4 инструкции, прокомментированные в тексте программы.
Контур создается в конструкторе формы. Когда курсор находится над клиентской областью формы, нажатие любой кнопки мыши вызывает метод StartFigure, начинающий новую фигуру. Вызов AddLine во время исполнения метода OnMouseMove добавляет к контуру новую линию, а метод OnPaint просто вызывает DrawPath.
| netlib.narod.ru | < Назад | Оглавление | Далее > |