Поделиться через


Создание рисунков и чертежей элементов управления

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

Если вы создаете составной элемент управления, то есть элемент управления, наследующий от UserControl одного или одного из существующих элементов управления Windows Forms, можно переопределить стандартное графическое представление и предоставить собственный графический код.

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

При отрисовке элемента управления используются следующие элементы:

  • Функции рисования, предоставляемые базовым классом System.Windows.Forms.Control.
  • Обязательные элементы библиотеки графических объектов GDI.
  • Геометрия области рисования.
  • Процедура высвобождения графических ресурсов.

Рисунок, предоставленный контролем

Базовый класс Control предоставляет функции рисования с помощью события Paint. Элемент управления вызывает событие каждый Paint раз, когда он должен обновить своё отображение и завершил его отрисовку. Дополнительные сведения о событиях в .NET см. в разделе "Обработка и создание событий".

Класс данных событий для события Paint, PaintEventArgs, содержит данные, необходимые для рисования элемента управления, — маркер для графического объекта и прямоугольник, представляющий область для рисования.

public class PaintEventArgs : EventArgs, IDisposable
{

    public System.Drawing.Rectangle ClipRectangle {get;}
    public System.Drawing.Graphics Graphics {get;}

    // Other properties and methods.
}
Public Class PaintEventArgs
    Inherits EventArgs
    Implements IDisposable

    Public ReadOnly Property ClipRectangle As System.Drawing.Rectangle
    Public ReadOnly Property Graphics As System.Drawing.Graphics

    ' Other properties and methods.
End Class

Graphics — это управляемый класс, который инкапсулирует функциональные возможности рисования, как описано в разделе, посвященном GDI, далее в этой статье. ClipRectangle является экземпляром структуры Rectangle и определяет доступную область, где возможно рисование элемента управления. Разработчик элемента управления может вычислить ClipRectangle с помощью свойства ClipRectangle элемента управления, как описано в обсуждении геометрии далее в этой статье.

OnPaint

Элемент управления должен предоставлять логику отрисовки путем переопределения метода OnPaint, который он наследует от Control. OnPaint получает доступ к графическому объекту и прямоугольнику для рисования с помощью свойств Graphics и ClipRectangle экземпляра PaintEventArgs, переданного в него.

В следующем коде используется пространство имен System.Drawing:

protected override void OnPaint(PaintEventArgs e)
{
    // Call the OnPaint method of the base class.
    base.OnPaint(e);

    // Declare and instantiate a new pen that will be disposed of at the end of the method.
    using var myPen = new Pen(Color.Aqua);

    // Create a rectangle that represents the size of the control, minus 1 pixel.
    var area = new Rectangle(new Point(0, 0), new Size(this.Size.Width - 1, this.Size.Height - 1));

    // Draw an aqua rectangle in the rectangle represented by the control.
    e.Graphics.DrawRectangle(myPen, area);
}
Protected Overrides Sub OnPaint(e As PaintEventArgs)
    MyBase.OnPaint(e)

    ' Declare and instantiate a drawing pen.
    Using myPen = New System.Drawing.Pen(Color.Aqua)

        ' Create a rectangle that represents the size of the control, minus 1 pixel.
        Dim area = New Rectangle(New Point(0, 0), New Size(Me.Size.Width - 1, Me.Size.Height - 1))

        ' Draw an aqua rectangle in the rectangle represented by the control.
        e.Graphics.DrawRectangle(myPen, area)

    End Using
End Sub

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

Замечание

Не вызывайте OnPaint непосредственно из элемента управления; вместо этого вызовите метод Invalidate (наследуется от Control) или другой метод, который вызывает Invalidate. Метод Invalidate, в свою очередь, вызывает OnPaint. Метод Invalidate перегружен и, в зависимости от аргументов, передаваемых в Invalidatee, перерисовывает часть области экрана или весь экран.

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

SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.ResizeRedraw, True)

OnPaintBackground

Базовый класс Control определяет другой метод, который удобен для рисования, метод OnPaintBackground.

protected virtual void OnPaintBackground(PaintEventArgs e);
Protected Overridable Sub OnPaintBackground(e As PaintEventArgs)

OnPaintBackground рисует фон (и таким образом, фигуру) окна, что гарантированно будет быстрым, в то время как OnPaint закрашивает детали и может быть медленнее, поскольку отдельные запросы рисования объединяются в одно событие Paint, охватывающее все области, которые необходимо перерисовать. Может потребоваться вызвать OnPaintBackground, если, например, нужно нарисовать градиентный фон для элемента управления.

Хотя OnPaintBackground имеет название, похожее на событие, и принимает тот же аргумент, что и метод OnPaint, OnPaintBackground не является настоящим методом события. Событие PaintBackground отсутствует, и OnPaintBackground не вызывает делегаты событий. При переопределении метода OnPaintBackground производному классу не обязательно вызывать метод OnPaintBackground своего базового класса.

Основы GDI+

Класс Graphics предоставляет методы для рисования различных фигур, таких как круги, треугольники, дуги и эллипсы, а также методы для отображения текста. Пространство System.Drawing имен содержит пространства имен и классы, которые инкапсулируют графические элементы, такие как фигуры (круги, прямоугольники, дуги и другие), цвета, шрифты, кисти и т. д.

Геометрия области рисования

Свойство ClientRectangle элемента управления указывает прямоугольную область, доступную для элемента управления на экране пользователя, а свойство ClipRectangle объекта PaintEventArgs — закрашиваемую область. Элементу управления может потребоваться закрасить только часть его доступной области, например в случае, когда изменяется небольшой раздел элемента управления. В таких ситуациях разработчик элемента управления должен вычислить фактический прямоугольник для рисования и передать его в Invalidate. Перегруженные версии Invalidate, принимающие Rectangle или Region в качестве аргумента, используют этот аргумент для создания свойства ClipRectangle элемента PaintEventArgs.

Освобождение графических ресурсов

Графические ресурсы являются ресурсоемкими, поскольку они используют системные ресурсы. К таким объектам относятся экземпляры класса System.Drawing.Graphics и экземпляры System.Drawing.Brush, System.Drawing.Pen и других графических классов. Графический ресурс следует создавать только в том случае, когда он вам нужен, и его следует сразу выпустить, как только вы завершите его использование. Если вы создаете экземпляр типа, который реализует интерфейс IDisposable, вызовите его метод Dispose, когда завершите работу с ним, чтобы освободить ресурсы.

См. также

Пользовательские элементы управления