Рисование в Windows Forms: линии, фигуры и изображения

Windows Forms — это фреймворк для создания настольных приложений на Windows. Он предоставляет визуальный дизайнер для размещения элементов управления и набор классов для программного рисования. В этом руководстве показано, как добавлять линии, фигуры и изображения в форму с помощью Visual Studio 2019 Community Edition.
Что такое встроенные классы для рисования графики?
Windows Forms использует язык C#. Для рисования на форме предназначены несколько основных классов: Graphics, Pen, Color и Brush. Коротко:
- Graphics — объект контекста рисования; предоставляет методы для отрисовки линий, фигур и изображений.
- Pen — определяет параметры «ручки» для обводки: цвет, ширину, стиль штрихов и концы линий.
- Brush (SolidBrush, HatchBrush, TextureBrush) — определяет заливку фигур: сплошной цвет, штриховку или текстуру.
- Rectangle/Point/PointF — структуры для задания координат и размеров.
| Класс | Описание |
|---|---|
| Graphics | Позволяет рисовать линии и фигуры на канве. Методы: DrawLine(Pen, Point1, Point2), DrawRectangle(x,y,width,height), DrawPolygon(Pen, PointF[]) и др. |
| Pen | Определяет свойства линии (цвет, толщина, DashStyle). Метод: SetLineCap(LineCap, LineCap, DashCap) и свойства StartCap/EndCap. |
| Color | Цвет, задаваемый значениями R, G, B и опционально альфа-каналом. |
| SolidBrush, HatchBrush, TextureBrush | Классы-щетки для заливки фигур: сплошной цвет, узор или изображение. |
| Rectangle, Line, Polygon, Ellipse | Структуры/шаблоны для представления геометрических фигур. |
Важно: многие методы используют пиксельные координаты, где (0,0) — верхний левый угол формы.
Как добавить обработчик Paint при загрузке формы
Для программного рисования нужно подписаться на событие Paint формы. Это гарантирует, что рисование будет корректно перерисовываться при обновлении интерфейса.
- Добавьте функцию Paint в код формы:
private void Form1_Paint(object sender, PaintEventArgs e)
{
// Код рисования сюда
}- Откройте вкладку Design (Дизайн).
- В окне Properties выберите значок молнии, чтобы открыть вкладку событий.
- Для события Paint укажите функцию Form1_Paint. Тогда метод будет вызываться при перерисовке формы.
Совет: не храните в Paint долгие операции (чтение файлов, долгие расчёты). Paint должен быть быстрым — иначе UI будет «подтормаживать».
Как рисовать линии на форме
Для линии нужны Color, Pen и метод DrawLine() объекта Graphics (в PaintEventArgs e).
- Создайте цвет и объект Pen внутри обработчика Paint:
Color black = Color.FromArgb(255, 0, 0, 0);
Pen blackPen = new Pen(black);- Нарисуйте линию от одной точки до другой:
e.Graphics.DrawLine(blackPen, 300, 200, 800, 200);- Настройте свойства Pen для изменения толщины, стиля штрихов и наконечников:
blackPen.Width = 20;
blackPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
blackPen.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
e.Graphics.DrawLine(blackPen, 300, 200, 800, 200);- Запустите приложение в Visual Studio, чтобы увидеть результат.
Важно: координаты в DrawLine указываются в пикселях относительно верхнего левого угла поверхности рисования.
Как рисовать прямоугольники и окружности
Можно использовать как методы DrawRectangle/DrawEllipse, так и структуры Rectangle/Point для удобства.
- Подготовьте Pen и Color, затем вызовите DrawRectangle:
Color red = Color.FromArgb(255, 255, 0, 0);
Pen redPen = new Pen(red);
redPen.Width = 5;
e.Graphics.DrawRectangle(redPen, 100, 100, 500, 200);- Можно создать объект Rectangle и передать его в метод:
Rectangle rectangle = new Rectangle(100, 350, 500, 200);
e.Graphics.DrawRectangle(redPen, rectangle);- Рисование окружности (эллипса):
Color green = Color.FromArgb(255, 0, 255, 0);
Pen greenPen = new Pen(green);
greenPen.Width = 5;
e.Graphics.DrawEllipse(greenPen, 400, 150, 400, 400);Примечание: аргументы DrawEllipse(x, y, width, height) задают рамку эллипса. Если width == height, будет окружность. x и y — левый верхний угол ограничивающего прямоугольника, а не центр круга.
- Рисование многоугольников через DrawPolygon:
Color blue = Color.FromArgb(255, 0, 0, 255);
Pen bluePen = new Pen(blue);
bluePen.Width = 5;
PointF[] coordinatesForTriangle = new PointF[] {
new PointF(400, 150),
new PointF(300, 300),
new PointF(500, 300)
};
e.Graphics.DrawPolygon(bluePen, coordinatesForTriangle);DrawPolygon соединяет точки в порядке их следования и закрывает контур между последней и первой точками.
Как использовать Brush для заполнения фигур цветом
Для закрашивания фигур применяются методы FillRectangle, FillEllipse и FillPolygon. Вместо Pen они принимают объект Brush.
- Создайте кисть SolidBrush:
Color purple = Color.FromArgb(255, 128, 0, 0);
SolidBrush solidBrush = new SolidBrush(purple);- Закрасьте фигуры:
e.Graphics.FillRectangle(solidBrush, 50, 50, 200, 250);
e.Graphics.FillEllipse(solidBrush, 300, 50, 200, 200);
e.Graphics.FillPolygon(solidBrush, new PointF[] { new PointF(700, 150), new PointF(600, 300), new PointF(800, 300) });- Можно передавать объект Rectangle:
Rectangle rectangle = new Rectangle(100, 350, 500, 200);
e.Graphics.FillRectangle(solidBrush, rectangle);- HatchBrush — заливка узором:
Color blue = Color.FromArgb(255, 0, 0, 255);
Color green = Color.FromArgb(255, 0, 255, 0);
HatchBrush hatchBrush = new HatchBrush(HatchStyle.Horizontal, green, blue);
e.Graphics.FillRectangle(hatchBrush, 50, 50, 200, 250);- TextureBrush — заливка изображением:
Bitmap image = (Bitmap)Image.FromFile(@"C:\Users\Sharl\Desktop\flag.bmp", true);
TextureBrush textureBrush = new TextureBrush(image);
e.Graphics.FillRectangle(textureBrush, 100, 100, 500, 400);Замечание: при использовании Image.FromFile убедитесь, что путь корректен и приложение имеет права на чтение файла.
Как рендерить изображения на форме
Для отображения растрового изображения можно использовать PictureBox или рисовать напрямую через Graphics.DrawImage.
- PictureBox пример:
PictureBox picture = new PictureBox();
picture.ImageLocation = @"C:\Users\Sharl\Desktop\flagLarge.bmp";
picture.SizeMode = PictureBoxSizeMode.AutoSize;
this.Controls.Add(picture);- Прямое рисование изображения в Paint:
Image img = Image.FromFile(@"C:\Users\Sharl\Desktop\flagLarge.bmp");
e.Graphics.DrawImage(img, new Rectangle(50,50,img.Width/2,img.Height/2));- Запустите приложение, чтобы убедиться, что изображение отображается.
Совет по производительности: при частой перерисовке кэшируйте Bitmap в поле класса и освобождайте ресурсы (Dispose) при закрытии формы.
Отладка, распространённые ошибки и когда это не сработает
- Проблема: ничего не видно. Причина: код рисования не вызывается — не подписаны на Paint или рисование перерисовывается кистью Background. Решение: убедитесь, что Form1_Paint подключён, и не удаляйте базовую логику OnPaint.
- Проблема: «мерцание» при перерисовке. Решение: включите двойную буферизацию формы (this.DoubleBuffered = true) или используйте ControlStyles для оптимизации.
- Проблема: путь к файлу изображения недоступен. Решение: используйте относительные пути или ресурсный менеджер, обрабатывайте исключения при загрузке файлов.
- Кейс, когда метод не подходит: если вам нужна кроссплатформенная графика (Linux/Mac), WinForms не лучший выбор. Рассмотрите SkiaSharp или WPF для расширенных возможностей рендеринга на Windows.
Важно: System.Drawing и WinForms оптимизированы под Windows. В окружениях .NET Core/5+ поведение System.Drawing на non-Windows может быть ограничено.
Шаблон проверки качества (Критерии приёмки)
- Обработчик Paint подписан и вызывается при перерисовке.
- Линии и фигуры отображаются в ожидаемых координатах и размерах.
- При изменении размеров формы всё перерисовывается корректно.
- Нет ощутимого торможения интерфейса при перерисовке обычных сцен.
- Ресурсы изображения корректно загружаются и освобождаются (Dispose вызван).
Тест-кейсы и критерии приёмки
- TC1 — Отрисовка линии: запустить форму, убедиться, что линия от (300,200) до (800,200) видна и имеет заданную толщину.
- TC2 — Отрисовка круга: при width=height окружность позиционирована по рамке, x,y — верхний левый угол.
- TC3 — Заполнение текстурой: изображение загружается и корректно используется в TextureBrush.
- TC4 — Перерисовка при изменении размера: изменить размер окна, убедиться, что фигуры корректно обновляются.
Критерии приёмки: все тесты проходят и нет утечек памяти при многократном открытии/закрытии формы.
Практические советы и эвристики
- Разделяйте логику расчёта координат и сам код рисования. Рассчитайте точки и размеры заранее, а в Paint только рисуйте.
- Делайте перерисовку детерминированной: при изменении данных вызывайте Invalidate() для перерисовки.
- Кэшируйте тяжёлые ресурсы (Bitmap, сложные Path’ы) между вызовами Paint.
- Не храните потоки IO в Paint: загружайте данные в фоновом потоке.
Альтернативные подходы
- WPF — для векторной графики и аппаратно-ускоренной отрисовки на Windows.
- SkiaSharp — кроссплатформенная библиотека для высокопроизводительной 2D-графики.
- ImageSharp — современная библиотека для обработки изображений вне System.Drawing.
Модель принятия решения: если приложение целиком привязано к Windows Forms и не требует аппаратного ускорения — используйте WinForms. Если нужна кроссплатформенность или сложная анимация — рассмотрите SkiaSharp или WPF.
Быстрая методология разработки рисовалки (мини-методология)
- Спроектируйте координатную систему и размеры базовых фигур.
- Реализуйте классы/методы, возвращающие Point/Rectangle для каждой фигуры.
- В Paint вызывайте только методы рисования, опираясь на подготовленные данные.
- Добавьте кеширование и валидацию ресурсов (Bitmap, Brush).
- Напишите тесты, проверяющие видимые пиксели для ключевых сценариев.
Рольные чек-листы
Разработчик:
- Подписал обработчик Paint.
- Использует Dispose для кистей и изображений.
- Добавил двойную буферизацию для формы.
Тестировщик:
- Проверил перерисовку при изменении размеров.
- Проверил отображение на мониторах с разным DPI.
- Проверил поведение при отсутствии файлов изображений.
Дизайнер:
- Предоставил набор цветов и размеров в пикселях.
- Уточнил точки привязки (anchor points) и порядок слоёв.
Совместимость и советы по миграции
- WinForms исторически работает на .NET Framework. Начиная с .NET Core 3.x и .NET 5/6/7, WinForms поддерживается в Windows-ориентированных релизах платформы. Если нужна кроссплатформенность — выбирайте альтернативы.
- System.Drawing критически завязан на GDI+ и Windows. Для серверной обработки изображений или кроссплатформенности используйте SkiaSharp или ImageSharp.
Короткий словарь (1 строка каждый)
- Graphics — контекст рисования, через который вызываются Draw* методы.
- Pen — объект для обводки линий и контуров.
- Brush — объект для заливки внутренних областей фигур.
- Rectangle/PointF — структуры для координат и размеров.
- DoubleBuffered — режим для снижения мерцания при перерисовке.
Пример решения принятия (Mermaid): выбрать технологию графики
flowchart TD
A[Нужна графика в приложении?] --> B{Кроссплатформенность}
B -- Да --> C[SkiaSharp / ImageSharp]
B -- Нет --> D{Аппаратное ускорение}
D -- Да --> E[WPF]
D -- Нет --> F[WinForms 'Graphics, GDI+']
C --> G[Реализовать рендеринг]
E --> G
F --> GКраткое резюме
Вы научились подключать обработчик Paint, рисовать линии, прямоугольники, окружности и многоугольники, заполнять фигуры кистями и рендерить изображения в Windows Forms. Также получили рекомендации по отладке, тестированию и альтернативам для кроссплатформенных или производительных задач.
Важно: проверяйте права доступа к файлам изображений и не выполняйте тяжёлые операции в обработчике Paint.
Ключевые шаги на практике: добавьте Form1_Paint, создайте Pen/Brush, вызовите e.Graphics.Draw или e.Graphics.Fill, тестируйте и кэшируйте ресурсы.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone