Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
La pintura personalizada de controles es una de las muchas tareas complicadas que Windows Forms simplifica. Cuando crea un control personalizado, tiene muchas opciones disponibles para controlar la apariencia gráfica del control. Si va a crear un control personalizado, es decir, un control que hereda de Control, se usa código para representar su representación gráfica.
Si está creando un control compuesto, es decir, un control que hereda ya sea de UserControl o de uno de los controles existentes de Windows Forms, puede sobrescribir la representación gráfica estándar y aportar su propio código gráfico.
Si desea proporcionar representación personalizada para un control existente sin crear un nuevo control, controle el Paint evento que le permite dibujar sobre un control.
Los elementos siguientes están implicados en la representación de controles:
- La funcionalidad de dibujo proporcionada por la clase base System.Windows.Forms.Control.
- Los elementos esenciales de la biblioteca de gráficos GDI.
- La geometría de la región de dibujo.
- El procedimiento para liberar recursos de gráficos.
Dibujo proporcionado por el departamento de control
La clase base Control proporciona funcionalidad de dibujo a través de su evento Paint. Un control genera el Paint evento cada vez que necesita actualizar su pantalla y ha completado su representación gráfica. Para obtener más información sobre los eventos en .NET, consulte Control y generación de eventos.
La clase de datos del evento Paint, PaintEventArgs, contiene los datos necesarios para dibujar un control: un manipulador para un objeto gráfico y un rectángulo que representa la región en la que se va a dibujar.
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 es una clase administrada que encapsula la funcionalidad de dibujo, tal y como se describe en el análisis de GDI más adelante en este artículo. ClipRectangle es una instancia de la estructura de Rectangle y define el área disponible en la que puede dibujarse un control. Un desarrollador de controles puede calcular el valor de ClipRectangle mediante la propiedad ClipRectangle de un control, tal y como se describe en el análisis de geometría más adelante en este artículo.
OnPaint
Un control debe proporcionar la lógica de representación reemplazando el método OnPaint que hereda de Control. OnPaint obtiene acceso a un objeto gráfico y a un rectángulo en el que dibujar mediante las propiedades Graphics y ClipRectangle de la instancia de PaintEventArgs que se le ha pasado.
El siguiente código usa el espacio de nombres 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
El método OnPaint de la clase Control base no implementa ninguna funcionalidad de dibujo, sino que simplemente invoca los delegados de evento que están registrados en el evento Paint. Cuando reemplace OnPaint, asegúrese de llamar al método OnPaint de la clase base de modo que los delegados registrados reciban el evento Paint. Sin embargo, los controles que pintan toda la superficie no deben invocar el OnPaint de la clase base, ya que este introduce parpadeo.
Nota:
No invoque OnPaint directamente desde el control; en su lugar, invoque el método Invalidate (heredado de Control) o algún otro método que invoque Invalidate. A su vez, el método Invalidate invoca OnPaint. El método Invalidate está sobrecargado y, en función de los argumentos proporcionados en Invalidatee
, vuelve a dibujar parte o toda el área de su pantalla.
El código del método OnPaint del control se ejecutará cuando se dibuje por primera vez el control y cada vez que se actualice. Para asegurarse de que el control se vuelve a dibujar cada vez que cambia de tamaño, agregue la siguiente línea al constructor del control:
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.ResizeRedraw, True)
OnPaintBackground
La clase Control base define otro método que es útil para dibujar, el método OnPaintBackground.
protected virtual void OnPaintBackground(PaintEventArgs e);
Protected Overridable Sub OnPaintBackground(e As PaintEventArgs)
OnPaintBackground pinta el fondo (y de este modo, la forma) de la ventana y se garantiza que es rápido, mientras que OnPaint pinta los detalles y podría ser más lento, ya que las solicitudes de pintura individuales se combinan en un evento Paint que cubre todas las áreas que deben volver a dibujarse. Es posible que quiera invocar el OnPaintBackground si, por ejemplo, quiere dibujar un fondo de color degradado para el control.
Aunque OnPaintBackground tiene una nomenclatura similar a un evento y toma el mismo argumento que el método OnPaint
, OnPaintBackground
no es un verdadero método de evento. No hay ningún evento PaintBackground
y OnPaintBackground
no invoca los delegados de eventos. Al reemplazar el método OnPaintBackground
, no es necesario que una clase derivada invoque el método OnPaintBackground
de su clase base.
Conceptos básicos de GDI+
La clase Graphics proporciona métodos para dibujar diversas formas, como círculos, triángulos, arcos y elipses, y métodos para mostrar texto. El espacio de nombres System.Drawing contiene espacios de nombres y clases que encapsulan elementos gráficos como formas (círculos, rectángulos, arcos y otros), colores, fuentes, pinceles, etc.
Geometría de la región de dibujo
La propiedad ClientRectangle de un control especifica la región rectangular disponible para el control en la pantalla del usuario, mientras que la propiedad ClipRectangle de PaintEventArgs especifica el área que se pinta. Es posible que un control solo tenga que pintar una parte de su área disponible, como sucede cuando se cambia una pequeña sección de la pantalla del control. En esas situaciones, un desarrollador de controles debe calcular el rectángulo real en el que dibujar y pasarlo a Invalidate. Las versiones sobrecargadas de Invalidate que toman un Rectangle o Region como argumento usan ese argumento para generar la propiedad ClipRectangle de PaintEventArgs.
Liberación de recursos gráficos
Los objetos gráficos son caros porque usan recursos del sistema. Estos objetos incluyen instancias de la clase System.Drawing.Graphics e instancias de System.Drawing.Brush, System.Drawing.Pen y otras clases de gráficos. Es importante que cree un recurso de gráficos solo cuando lo necesite y lo libere en cuanto haya terminado de usarlo. Si crea una instancia de un tipo que implementa la interfaz IDisposable, llame a su método Dispose cuando haya terminado de usarla para liberar recursos.
Consulte también
.NET Desktop feedback