Cómo: Desarrollar un control de formularios Windows Forms sencillo

Actualización: noviembre 2007

En esta sección se ofrece un tutorial que describe los pasos básicos para crear un control de formularios Windows Forms personalizado. El control sencillo desarrollado en este tutorial permite modificar la alineación de su propiedad Text. No provoca ni controla eventos.

Para crear un control personalizado sencillo

  1. Defina una clase que se derive de System.Windows.Forms.Control.

    Public Class FirstControl
       Inherits Control
    
    End Class
    
    public class FirstControl:Control{}
    
  2. Defina propiedades. (No es necesario definir propiedades, ya que los controles heredan muchas propiedades de la clase Control, aunque para la mayoría de los controles personalizados se suelen definir propiedades adicionales.) En el fragmento de código siguiente se define una propiedad denominada TextAlignment que FirstControl utiliza para dar formato a la apariencia de la propiedad Text heredada de Control. Para obtener más información sobre la definición de propiedades, vea Información general sobre propiedades.

    ' ContentAlignment is an enumeration defined in the System.Drawing
    ' namespace that specifies the alignment of content on a drawing 
    ' surface.
    Private alignmentValue As ContentAlignment = ContentAlignment.MiddleLeft
    
    <Category("Alignment"), Description("Specifies the alignment of text.")> _
    Public Property TextAlignment() As ContentAlignment
    
       Get
          Return alignmentValue
       End Get
       Set
          alignmentValue = value
    
          ' The Invalidate method invokes the OnPaint method described 
          ' in step 3.
          Invalidate()
       End Set
    End Property
    
    // ContentAlignment is an enumeration defined in the System.Drawing
    // namespace that specifies the alignment of content on a drawing 
    // surface.
    private ContentAlignment alignmentValue = ContentAlignment.MiddleLeft;
    

    Cuando se establece una propiedad que cambia la apariencia visual del control, se debe invocar el método Invalidate para volver a dibujar el control. Invalidate se define en la clase base Control.

  3. Reemplace el método protegido OnPaint heredado de Control para proporcionar lógica de representación al control. Si no reemplaza OnPaint, el control no podrá dibujarse a sí mismo. En el fragmento de código siguiente, el método OnPaint muestra la propiedad Text heredada de Control con la alineación especificada por el campo alignmentValue.

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
    
       MyBase.OnPaint(e)
       Dim style As New StringFormat()
       style.Alignment = StringAlignment.Near
       Select Case alignmentValue
          Case ContentAlignment.MiddleLeft
             style.Alignment = StringAlignment.Near
          Case ContentAlignment.MiddleRight
             style.Alignment = StringAlignment.Far
          Case ContentAlignment.MiddleCenter
             style.Alignment = StringAlignment.Center
       End Select
    
       ' Call the DrawString method of the System.Drawing class to write   
       ' text. Text and ClientRectangle are properties inherited from
       ' Control.
       e.Graphics.DrawString( _
           me.Text, _
           me.Font, _
           New SolidBrush(ForeColor), _
           RectangleF.op_Implicit(ClientRectangle), _
           style)
    
    End Sub
    
    protected override void OnPaint(PaintEventArgs e) 
    {   
        base.OnPaint(e);
        StringFormat style = new StringFormat();
        style.Alignment = StringAlignment.Near;
        switch (alignmentValue) 
        {
            case ContentAlignment.MiddleLeft:
                style.Alignment = StringAlignment.Near;
                break;
            case ContentAlignment.MiddleRight:
                style.Alignment = StringAlignment.Far;
                break;
            case ContentAlignment.MiddleCenter:
                style.Alignment = StringAlignment.Center;
                break;
        }
    
        // Call the DrawString method of the System.Drawing class to write   
        // text. Text and ClientRectangle are properties inherited from
        // Control.
        e.Graphics.DrawString(
            Text, 
            Font, 
            new SolidBrush(ForeColor), 
            ClientRectangle, style);
    
    } 
    
  4. Proporcione atributos para el control. Los atributos permite a los diseñadores visuales mostrar el control y sus propiedades y evento correctamente en tiempo de diseño. El fragmento de código siguiente aplica atributos a la propiedad TextAlignment. En un diseñador como Visual Studio, el atributo Category (que aparece en el fragmento de código) hace que se muestre la propiedad en una categoría lógica. El atributo Description hace que se muestre una cadena descriptiva en la parte inferior de la ventana Propiedades cuando se selecciona la propiedad TextAlignment. Para obtener más información sobre controles, vea Atributos en tiempo de diseño para componentes.

    <Category("Alignment"), Description("Specifies the alignment of text.")> _
    Public Property TextAlignment() As ContentAlignment
    
    [
    Category("Alignment"),
    Description("Specifies the alignment of text.")
    ]
    
  5. (opcional) Proporcione recursos para el control. Para proporcionar un recurso, como un mapa de bits, al control, utilice una opción del compilador (/res para C#) para empaquetar recursos con el control. En tiempo de ejecución, el recurso se puede recuperar utilizando los métodos de la clase ResourceManager. Para obtener más información sobre cómo crear y utilizar los recursos, vea Recursos en aplicaciones.

  6. Compile e implemente el control. Para compilar e implementar FirstControl, realice los pasos siguientes.

    1. Guarde el código del siguiente ejemplo en un archivo de código fuente (como FirstControl.cs o FirstControl.vb).

    2. Compile el código fuente en un ensamblado y guárdelo en el directorio de la aplicación. Para ello, ejecute el siguiente comando desde el directorio que contiene el archivo de código fuente.

      vbc /t:library /out:[path to your application's directory]/CustomWinControls.dll /r:System.dll /r:System.Windows.Forms.dll /r:System.Drawing.dll FirstControl.vb
      
      csc /t:library /out:[path to your application's directory]/CustomWinControls.dll /r:System.dll /r:System.Windows.Forms.dll /r:System.Drawing.dll FirstControl.cs
      

      La opción del compilador /t:library indica al compilador que el ensamblado que se está creando es una biblioteca (y no un ejecutable). La opción /out especifica la ruta de acceso y el nombre del ensamblado. La opción /r indica el nombre de los ensamblados a los que hace referencia el código. En este ejemplo, se crea un ensamblado privado que sólo pueden utilizar sus aplicaciones. Por tanto, debe guardarlo en el directorio de su aplicación. Para obtener más información sobre cómo empaquetar e implementar un control para la distribución, vea Implementar aplicaciones de .NET Framework.

En el siguiente ejemplo se muestra el código de FirstControl. El control está incluido en el espacio de nombres CustomWinControls. Un espacio de nombres proporciona una agrupación lógica de tipos relacionados. El control se puede crear en un espacio de nombres nuevo o en uno existente. En C#, la declaración using (en Visual Basic, Imports) permite el acceso a los tipos desde un espacio de nombres sin utilizar el nombre completo del tipo. En el ejemplo siguiente, la declaración using permite al código tener acceso a la clase Control desde System.Windows.Forms simplemente como Control en lugar de tener que usar el nombre completo de System.Windows.Forms.Control.

Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms


Public Class FirstControl
   Inherits Control

   Public Sub New()
   End Sub 


   ' ContentAlignment is an enumeration defined in the System.Drawing
   ' namespace that specifies the alignment of content on a drawing 
   ' surface.
   Private alignmentValue As ContentAlignment = ContentAlignment.MiddleLeft

   <Category("Alignment"), Description("Specifies the alignment of text.")> _
   Public Property TextAlignment() As ContentAlignment

      Get
         Return alignmentValue
      End Get
      Set
         alignmentValue = value

         ' The Invalidate method invokes the OnPaint method described 
         ' in step 3.
         Invalidate()
      End Set
   End Property


   Protected Overrides Sub OnPaint(e As PaintEventArgs)

      MyBase.OnPaint(e)
      Dim style As New StringFormat()
      style.Alignment = StringAlignment.Near
      Select Case alignmentValue
         Case ContentAlignment.MiddleLeft
            style.Alignment = StringAlignment.Near
         Case ContentAlignment.MiddleRight
            style.Alignment = StringAlignment.Far
         Case ContentAlignment.MiddleCenter
            style.Alignment = StringAlignment.Center
      End Select

      ' Call the DrawString method of the System.Drawing class to write   
      ' text. Text and ClientRectangle are properties inherited from
      ' Control.
      e.Graphics.DrawString( _
          me.Text, _
          me.Font, _
          New SolidBrush(ForeColor), _
          RectangleF.op_Implicit(ClientRectangle), _
          style)

   End Sub

End Class
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace CustomWinControls
{
    public class FirstControl : Control
    {

        public FirstControl()
        {

        }

        // ContentAlignment is an enumeration defined in the System.Drawing
        // namespace that specifies the alignment of content on a drawing 
        // surface.
        private ContentAlignment alignmentValue = ContentAlignment.MiddleLeft;

        [
        Category("Alignment"),
        Description("Specifies the alignment of text.")
        ]
        public ContentAlignment TextAlignment 
        {

            get 
            {
                return alignmentValue;
            }
            set 
            {
                alignmentValue = value;

                // The Invalidate method invokes the OnPaint method described 
                // in step 3.
                Invalidate(); 
            }
        }


        protected override void OnPaint(PaintEventArgs e) 
        {   
            base.OnPaint(e);
            StringFormat style = new StringFormat();
            style.Alignment = StringAlignment.Near;
            switch (alignmentValue) 
            {
                case ContentAlignment.MiddleLeft:
                    style.Alignment = StringAlignment.Near;
                    break;
                case ContentAlignment.MiddleRight:
                    style.Alignment = StringAlignment.Far;
                    break;
                case ContentAlignment.MiddleCenter:
                    style.Alignment = StringAlignment.Center;
                    break;
            }

            // Call the DrawString method of the System.Drawing class to write   
            // text. Text and ClientRectangle are properties inherited from
            // Control.
            e.Graphics.DrawString(
                Text, 
                Font, 
                new SolidBrush(ForeColor), 
                ClientRectangle, style);

        } 
    }
}

Utilizar el control personalizado en un formulario

En el siguiente ejemplo se muestra un formulario sencillo que utiliza FirstControl. Crea tres instancias de FirstControl, cada una con un valor distinto de la propiedad TextAlignment.

Para compilar y ejecutar este ejemplo

  1. Guarde el código del siguiente ejemplo en un archivo de código fuente (SimpleForm.cs o SimpleForms.vb).

  2. Compile el código fuente en un ensamblado ejecutable; para ello, ejecute el siguiente comando desde el directorio que contiene el archivo de código fuente.

    vbc /r:CustomWinControls.dll /r:System.dll /r:System.Windows.Forms.dll /r:System.Drawing.dll SimpleForm.vb
    
    csc /r:CustomWinControls.dll /r:System.dll /r:System.Windows.Forms.dll /r:System.Drawing.dll SimpleForm.cs
    

    CustomWinControls.dll es el ensamblado que contiene la clase FirstControl. Este ensamblado debe encontrarse en el mismo directorio que el archivo de código fuente del formulario que tiene acceso a él. (SimpleForm.cs o SimpleForms.vb).

  3. Ejecute SimpleForm.exe con el siguiente comando.

    SimpleForm
    
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms




Public Class SimpleForm
   Inherits System.Windows.Forms.Form

   Private firstControl1 As FirstControl

   Private components As System.ComponentModel.Container = Nothing


   Public Sub New()
      InitializeComponent()
   End Sub 





   Private Sub InitializeComponent()
      Me.firstControl1 = New FirstControl()
      Me.SuspendLayout()

      ' 
      ' firstControl1
      ' 
      Me.firstControl1.BackColor = System.Drawing.SystemColors.ControlDark
      Me.firstControl1.Location = New System.Drawing.Point(96, 104)
      Me.firstControl1.Name = "firstControl1"
      Me.firstControl1.Size = New System.Drawing.Size(75, 16)
      Me.firstControl1.TabIndex = 0
      Me.firstControl1.Text = "Hello World"
      Me.firstControl1.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter

      ' 
      ' SimpleForm
      ' 
      Me.ClientSize = New System.Drawing.Size(292, 266)
      Me.Controls.Add(firstControl1)
      Me.Name = "SimpleForm"
      Me.Text = "SimpleForm"
      Me.ResumeLayout(False)
   End Sub 


   <STAThread()>  _
   Shared Sub Main()
      Application.Run(New SimpleForm())
   End Sub 
End Class 
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace CustomWinControls
{

    public class SimpleForm : System.Windows.Forms.Form
    {
        private FirstControl firstControl1;

        private System.ComponentModel.Container components = null;

        public SimpleForm()
        {
            InitializeComponent();
        }

        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        private void InitializeComponent()
        {
            this.firstControl1 = new FirstControl();
            this.SuspendLayout();

            // 
            // firstControl1
            // 
            this.firstControl1.BackColor = System.Drawing.SystemColors.ControlDark;
            this.firstControl1.Location = new System.Drawing.Point(96, 104);
            this.firstControl1.Name = "firstControl1";
            this.firstControl1.Size = new System.Drawing.Size(75, 16);
            this.firstControl1.TabIndex = 0;
            this.firstControl1.Text = "Hello World";
            this.firstControl1.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;

            // 
            // SimpleForm
            // 
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.Add(this.firstControl1);
            this.Name = "SimpleForm";
            this.Text = "SimpleForm";
            this.ResumeLayout(false);

        }

        [STAThread]
        static void Main() 
        {
            Application.Run(new SimpleForm());
        }


    }
}

Vea también

Conceptos

Eventos de los controles de formularios Windows Forms

Otros recursos

Propiedades de los controles de formularios Windows Forms