Визуализация элементов управления Windows Forms
Отрисовка обозначает процесс создания визуального представления на экране пользователя. Элементы управления Windows Forms используют для отрисовки GDI (новую графическую библиотеку Windows). Управляемые классы, предоставляющие доступ к GDI, расположены в пространстве имен System.Drawing и его подпространствах имен.
В отрисовке элемента управления участвуют следующие элементы.
Функциональные возможности рисования, обеспечиваемые базовым классом System.Windows.Forms.Control.
Неотъемлемые элементы графической библиотеки GDI.
Геометрия области рисования.
Процедура освобождения графических ресурсов.
Функциональность рисования, предоставленная элементом управления
Базовый класс Control обеспечивает функциональные возможности рисования посредством его события Paint. Элемент управления инициирует событие Paint в случае необходимости обновления его отображения. Дополнительные сведения о событиях в .NET Framework см. в разделе Обработка и создание событий.
Класс данных события для события Paint, PaintEventArgs, содержит данные, необходимые для рисования элемента управления — дескриптор графического объекта и прямоугольного объекта, представляющих собой область для рисования. Эти объекты выделены полужирным шрифтом в следующем фрагменте кода.
Public Class PaintEventArgs
Inherits EventArgs
Implements IDisposable
Public ReadOnly Property ClipRectangle() As System.Drawing.Rectangle
...
End Property
Public ReadOnly Property Graphics() As System.Drawing.Graphics
...
End Property
' Other properties and methods.
...
End Class
public class PaintEventArgs : EventArgs, IDisposable {
public System.Drawing.Rectangle ClipRectangle {get;}
public System.Drawing.Graphics Graphics {get;}
// Other properties and methods.
...
}
Graphics является управляемым классом, инкапсулирующим функциональность рисования, как это описано при обсуждении GDI далее в этом разделе. ClipRectangle является экземпляром структуры Rectangle, определяющей доступные области, в которых можно нарисовать элемент управления. Разработчик элемента управления может вычислить ClipRectangle, используя свойство ClipRectangle элемента управления, как показано ниже при описании геометрии в этом разделе.
Элемент управления должен предоставить логику отрисовки с помощью переопределения метода OnPaint, наследующего от Control. OnPaint получает доступ к графическому объекту и прямоугольнику для рисования с помощью передаваемых ему свойств Graphics и ClipRectangle экземпляра PaintEventArgs.
Protected Overridable Sub OnPaint(pe As PaintEventArgs)
protected virtual void OnPaint(PaintEventArgs pe);
Метод OnPaint базового класса Control не реализует какой-либо функциональности рисования. Он лишь вызывает делегатов события, зарегистрированных с событием Paint. При переопределении OnPaint следует, как правило, вызвать метод OnPaint базового класса, чтобы зарегистрированные делегаты получили событие Paint. Однако элементы управления, вырисовывающие свои поверхности, не должны вызывать OnPaint базового класса, так как это вызовет мерцание изображения. Пример переопределения события Практическое руководство. Создание элемента управления, показывающего прогресс в форме Windows Forms содержится в разделе OnPaint.
Примечание
Не вызывайте OnPaint непосредственно из элемента управления. Вместо этого вызовите метод Invalidate (наследуемый от Control) или какой-либо другой метод, вызывающий Invalidate.В свою очередь, метод Invalidate запускает OnPaint.Метод Invalidate перегружается, и, в зависимости от аргументов, примененных для Invalidate e, элемент управления частично или полностью перерисует свою поверхность экрана.
Базовый класс Control определяет другой метод, полезный для рисования: метод OnPaintBackground.
Protected Overridable Sub OnPaintBackground(pevent As PaintEventArgs)
protected virtual void OnPaintBackground(PaintEventArgs pevent);
OnPaintBackground рисует фон (а значит, и форму) окна и гарантированно делает это быстро, в то время как OnPaint рисует детали и может работать медленнее, так как индивидуальные запросы на рисование объединены в одном событии Paint, которое перекрывает все области, которые должны быть перерисованы. Может возникнуть необходимость вызвать OnPaintBackground, например в случае, если потребуется нарисовать градиентный закрашенный фон для элемента управления.
Хотя OnPaintBackground имеет систему обозначений, сходную с системой обозначений события, и принимает такие же аргументы, как и метод OnPaint, OnPaintBackground не является истинным методом события. Событие PaintBackground не существует, и OnPaintBackground не вызывает делегаты событий. При переопределении метода OnPaintBackground производный класс не требуется для вызова метода OnPaintBackground его базового класса.
Основы GDI+
Класс Graphics предоставляет методы для рисования различных форм, таких как круги, треугольники, дуги и эллипсы, а также методы для отображения текста. Пространство имен System.Drawing и его подпространства содержат классы, инкапсулирующие графические элементы, такие как формы (круги, прямоугольники, дуги и др.), цвета, шрифты, кисти и т.д. Дополнительные сведения о GDI см. в разделе Использование управляемых графических классов. Основы GDI также приводятся в разделе Практическое руководство. Создание элемента управления, показывающего прогресс в форме Windows Forms.
Геометрия области рисования
Свойство ClientRectangle элемента управления задает прямоугольную область, доступную для элемента управления на экране пользователя, в то время как свойство ClipRectangle PaintEventArgs задает область, которая фактически нарисована. (Запомните, что рисование выполняется в методе события PaintEventArgs, получающим экземпляр Paint в качестве аргумента). Элемент управления может потребовать перерисовать только часть доступной области, как в случае, когда изменяется небольшая часть его изображения. В такой ситуации разработчик элемента управления должен рассчитать фактический прямоугольник, в котором будет вестись рисование, и передать его Invalidate. Перегруженные версии Invalidate, получающие Rectangle или Region в качестве аргумента, используют этот аргумент для создания свойства ClipRectangle PaintEventArgs.
Следующий фрагмент кода показывает, как пользовательский элемент управления FlashTrackBar рассчитывает прямоугольную область, в которой будет вестись рисование. Переменная client обозначает свойство ClipRectangle. Полный пример содержится в разделе Практическое руководство. Создание элемента управления, показывающего прогресс в форме Windows Forms.
Dim invalid As Rectangle = New Rectangle( _
client.X + lmin, _
client.Y, _
lmax - lmin, _
client.Height)
Invalidate(invalid)
Rectangle invalid = new Rectangle(
client.X + min,
client.Y,
max - min,
client.Height);
Invalidate(invalid);
Освобождение графических ресурсов
Графические объекты расходуют системные ресурсы. Такие объекты содержат экземпляры класса System.Drawing.Graphics, а также экземпляры System.Drawing.Brush, System.Drawing.Pen и другие графические классы. Важно, чтобы графический ресурс создавался только тогда, когда он действительно нужен, и освобождался сразу после его использования. При создании типа, реализующего интерфейс IDisposable, вызовите его метод Dispose после окончания работы с ним для освобождения ресурсов.
Следующий фрагмент кода показывает, как пользовательский элементе управления FlashTrackBar создает и освобождает ресурс Brush. Полный исходный код примера содержится в разделе Практическое руководство. Создание элемента управления, показывающего прогресс в форме Windows Forms.
Private baseBackground As Brush
private Brush baseBackground = null;
MyBase.OnPaint(e)
If (baseBackground Is Nothing) Then
If (myShowGradient) Then
baseBackground = New LinearGradientBrush(New Point(0, 0), _
New Point(ClientSize.Width, 0), _
StartColor, _
EndColor)
ElseIf (BackgroundImage IsNot Nothing) Then
baseBackground = New TextureBrush(BackgroundImage)
Else
baseBackground = New SolidBrush(BackColor)
End If
End If
base.OnPaint(e);
if (baseBackground == null) {
if (showGradient) {
baseBackground = new LinearGradientBrush(new Point(0, 0),
new Point(ClientSize.Width, 0),
StartColor,
EndColor);
}
else if (BackgroundImage != null) {
baseBackground = new TextureBrush(BackgroundImage);
}
else {
baseBackground = new SolidBrush(BackColor);
}
}
Protected Overrides Sub OnResize(ByVal e As EventArgs)
MyBase.OnResize(e)
If (baseBackground IsNot Nothing) Then
baseBackground.Dispose()
baseBackground = Nothing
End If
End Sub
protected override void OnResize(EventArgs e) {
base.OnResize(e);
if (baseBackground != null) {
baseBackground.Dispose();
baseBackground = null;
}
}
См. также
Задачи
Практическое руководство. Создание элемента управления, показывающего прогресс в форме Windows Forms