В предыдущем примере («Кораблик») мы использовали простые и очевидные методы рисования графических объектов класса Graphics, такие как FillRectangle() — закрасить прямоугольник, FillPie() — закрасить сектор и DrawEllipse() — нарисовать эллипс. Чуть более сложный метод FillPolygon() — закрашенный полигон.
Постановка задачи: «Требуется нарисовать в небе несколько парапланов, имеющих разные цвета и размеры».
Обсуждение. Пусть все парапланы будут геометрически подобны друг другу. Для задания контура параплана нужно задать метод с параметрами, задающими его местоположение и некоторый характерный размер. Для простоты примера будем задавать цвета случайным образом.
Наши действия:
На форме (Form1) размером 900х400 поместим две кнопки «Закрась!» и «Нарисуй!», создадим для них и для Form1 обработчики событий Click.
Нам понадобятся объекты классов Graphics, SolidBrush, Pen, Point (точнее, это структура), Region и GraphicsPath (он задан в библиотеке System.Drawing.Drawing2D — дополнение к System.Drawing!).
Будем применять методы класса Graphics:
FillPath() — заполнить замкнутую область, заданную объектом класса GraphicsPath;
DrawPath() — нарисовать контур (может быть и не замкнутым), заданный объектом класса GraphicsPath;
ExcludeClip() — обновить вырезанную область данного объекта Graphics, чтобы исключить из нее часть, определяемую объектом класса Region, который создается через конструктор
Region gp = new Region(pp); где pp – объект класса GraphicsPath;
ResetClip() — сбросить вырезанную область(ти) и сделать ее бесконечной (условно, анти_ExcludeClip()).
Метод ExcludeClip(Region reg) закрывает для рисования указанную область, оставляя другие части холста видимыми для рисования, а метод ResetClip() отменяет этот запрет.
Полями класса Form1 объявим объекты:
Graphics g; // холст
GraphicsPath pp; // контур фантома-дырки,
pp — объект класса GraphicsPath в System.Drawing.Drawing2D;
SolidBrush br; // кисть
Рисовать будем купол параплана, имеющего разное местоположение и размеры. Его контур зададим объектом класса GraphicsPath, для чего создадим метод:
private GraphicsPath paraplan(int x, int y, int r),
который возвращает контур купола параплана с центром в точке (x,y) и и характерным размером клетки r. Это ломаная прямая, проходящая через 8 точек.
Дополним конструктор Form1(), определим методы: Form1_Click(), button1_Click(), button2_Click().
Метод public Color RandomColor() — «Случайный цвет» является вспомогательным. Он позволит менять цвета контуров и закраски. Написан для демонстрации применения класса Random из библиотеки System.
Примечание: В этом примере мы обошлись одним классом — Form1.
В этот класс, в дополнение ко всем полям, свойствам и методам класса, унаследованных от класса Form, мы добавили в качестве полей три объекта (холст, контур, кисть), дополнили конструктор класса без изменения имени (принцип полиморфизма), добавили три метода обработки событий, а также методы paraplan() и RandomColor().
Остальное вам должно быть понятно из комментариев в тексте программы (файл Form1.cs):
// Пример рисования замкнутых областей // (C) В.Рычков, 2017 using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace парапланы { public partial class Form1 : Form { Graphics g; // холст GraphicsPath pp; // контур фантома-дырки SolidBrush br; // кисть public Form1() // конструктор формы { InitializeComponent(); g = Graphics.FromHwnd(this.Handle); // холст pp = paraplan(450, 130, 20); // положение и размер // фантома-дырки } // метод возвращает контур с центром в точке (x,y) // и размером клетки r. Нарисуйте его на бумаге. private GraphicsPath paraplan(int x, int y, int r) { int[,] pts = { { x-4*r, y }, { x-2*r, y-r }, { x+2*r, y-r }, { x+4*r, y }, { x+3*r, y+r }, { x+r, y }, { x-r, y }, { x-3*r, y+r }, { x-4*r, y } }; // параплан через массив pts Point[] pt = new Point[9]; // массив точек для gp byte[] typ = new byte[9]; // массив соединений for (int p = 0; p < 9; p++) { pt[p].X = pts[p, 0]; pt[p].Y = pts[p, 1]; typ[p] = (byte)PathPointType.Line; //ломаными, // PathPointType описан в System.Drawing.Drawing2D; }; GraphicsPath gp = new GraphicsPath(pt, typ); return gp; // возвращаем внутренняя часть формы } // создает фантом-дырку и рисует поверх нее параплан private void Form1_Click(object sender, EventArgs e) { // Метод обновляет отсеченную область gp Region gp = new Region(pp); g.ExcludeClip(gp); // Рисуем параплан большего размера GraphicsPath pp1 = paraplan(450, 180, 80); // контур br = new SolidBrush(RandomColor()); // кисть g.FillPath(br, pp1); // закраска } // сбрасывает дырку и рисует заплатку // кнопка "Закрась" private void button1_Click(object sender, EventArgs e) { g.ResetClip(); // сбрасывает вырезанную область и // делает ее бесконечной, анти_ExcludeClip(); br = new SolidBrush(RandomColor()); g.FillPath(br, pp); // ставим заплатку } // рисует контур другого параплана, кнопка "Нарисуй" private void button2_Click(object sender, EventArgs e) { GraphicsPath pp1 = paraplan(150, 80, 30); // Рисуем параплан меньшего размера Pen pen = new Pen(RandomColor(),4f); g.DrawPath(pen, pp1); } // случайный цвет - вспомогательный метод public Color RandomColor() { int r, g, b; byte[] bytes1 = new byte[3]; // массив 3 цветов Random rnd1 = new Random(); // объект класса rnd1.NextBytes(bytes1); // генерация массива r = Convert.ToInt16(bytes1[0]); g = Convert.ToInt16(bytes1[1]); b = Convert.ToInt16(bytes1[2]); return Color.FromArgb(r, g, b); // цвет через метод } } }
Цвет парапланов меняется при нажатии на кнопки и при клике на форме. Пока не будет нажата кнопка «Закрась», маленький параплан будет сохранять цвет фона. Поэкспериментируйте с программой.
Перейдем к рисованию сплайнами и кривыми Безье.
NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.
![]() |
![]() |
![]() |
![]() |
Очень понятно стало, зачем нужны объекты классов GraphicsPath и Region.