Creación de controles de Visual Basic .NET desde cero

Publicado: noviembre 30, 2007 en Categoria All

Creación de controles de Visual Basic .NET desde cero

Nunca he sentido la tentación de convertirme en programador de C++, ya que soy demasiado perezoso para trabajar tanto. Sin embargo, debo admitir que envidiaba a los programadores de C++ su capacidad para escribir controles visuales.

Los controles en Visual Basic® 6.0 y versiones anteriores se limitaban a controles compuestos (controles formados por otros) denominados UserControls. Escribir un control que tuviera su propia representación visual en la pantalla en Visual Basic 6.0 era una tarea entre difícil e imposible.

La buena noticia es que ahora Visual Basic .NET permite escribir todo tipo de controles visuales. Aún dispone de UserControls compuestos y también puede heredar de un control existente, como TextBox, y ampliarlo con nuevas capacidades. Es más, puede escribir un control visual desde cero que presente su propia interfaz.

En este artículo, haré una demostración de esta capacidad mediante la creación de un control visual completo desde cero. El control es un semáforo, es decir, un rectángulo con círculos en rojo, amarillo y verde. En la figura 1 se muestra la apariencia del control con cada una de las luces encendidas y con el color de fondo del control establecido en el color del sistema ControlDark.

Figura 1. Formulario con tres controles TrafficLight, cada uno con una luz diferente encendida.

Lo llamaremos control TrafficLight y podrá cambiar la luz activa, mediante código o mediante clics por parte del usuario.

Puesto que TrafficLight es un control de Windows Forms visual, heredará de la clase Control en el espacio de nombres System.Windows.Forms. Esto nos proporcionará gran cantidad de propiedades, métodos y eventos predefinidos. Entre ellos, se incluyen propiedades para el control de la apariencia, como ForeColor, BackColor, Size y Location, y eventos, como MouseOver y Click. Puede consultar la documentación de .NET para obtener una lista completa de los miembros de la clase Control.

La luz también necesitará las siguientes propiedades y eventos especiales:

Propiedad Status
Determina de qué color es la luz activada. Debe ser uno de los tres siguientes tipos de valores enumerados:

  • StatusRed: la luz roja está activada.
  • StatusYellow: la luz amarilla está activada.
  • StatusGreen: la luz verde está activada.

Propiedad BorderWidth
La anchura del dibujo de borde que rodea el semáforo.

Evento StatusChanged
Se desencadena cuando la propiedad Status cambia a un valor distinto, mediante código o clics por parte del usuario en una luz diferente.

Puesto que estos miembros no están en la clase base Control, será necesario incluir el código completo para controlarlos. También necesitaremos el código para dibujar el semáforo en la pantalla mediante el trazado del borde y los tres círculos con los colores adecuados. Finalmente, tendremos que controlar los clics realizados en un círculo para cambiar la luz activa y cambiar la propiedad Status cuando esto ocurra.

Para que este ejemplo esté tan listo para la producción como sea posible, también incluiremos un código para que el control funcione mejor con IDE de Visual Studio® .NET. Le asignaremos un icono adecuado para el cuadro de herramientas e incluiremos la lógica para que las propiedades se integren correctamente con las ventanas Propiedades.

Comencemos.

Paso 1: creación del tipo correcto de proyecto

Para crear una biblioteca en la que almacenar controles de Windows Forms, inicie un nuevo proyecto en Visual Basic .NET y seleccione el tipo de proyecto Biblioteca de controles de Windows. Dé al proyecto el nombre MyControls.

En el proyecto resultante se podrán almacenar varios controles de Windows Forms, cada uno en su propia clase. Sin embargo, sólo vamos a crear un control dentro del proyecto.

Paso 2: cambio de la clase base

La clase creada en la biblioteca de controles tomará automáticamente el nombre UserControl1 y, de forma predeterminada, heredará de la clase UserControl. Sería estupendo para crear un control compuesto, ya que bastaría con empezar a arrastrar otros controles desde el cuadro de herramientas hasta la superficie de diseño.

Sin embargo, como queremos crear nuestro propio control desde cero, tendremos que hacer algunos cambios. Cambie el nombre de la clase del control de UserControl1 a TrafficLight. A continuación, cambie la línea

    Inherits System.Windows.Forms.UserControl

por esta otra:

    Inherits System.Windows.Forms.Control

De esta forma, la clase más genérica Control se convertirá en la clase base. Observará que la superficie de diseño visual ya no estará disponible y que se sustituirá por una superficie de diseño de componentes.

Para mantener la coherencia del código, cambie el nombre del archivo de código UserControl1.vb por TrafficLight.vb. Para ello, en el Explorador de soluciones, haga clic con el botón secundario en el nombre del archivo de código y seleccione Cambiar nombre.

También necesitaremos un par de líneas de código en la parte superior del módulo de clase. Estableceremos Option Strict en On e importaremos un espacio de nombres que contenga determinados atributos que utilizaremos más tarde. A continuación se muestran las dos líneas que se deben escribir al principio del código:

Option Strict On
Imports System.ComponentModel
Paso 3: implementación de las propiedades y los eventos

Para implementar la propiedad Status, primero tendremos que crear una enumeración para los posibles valores de dicha propiedad. Inserte las líneas siguientes a continuación de la línea que comienza por Inherits:

Public Enum TrafficLightStatus
    statusRed = 1
    statusYellow = 2
    statusGreen = 3
End Enum

Esta enumeración es pública, es decir, los formularios que utilicen el control tendrán acceso a ella.

A continuación de esta líneas, agregue las tres líneas siguientes:

Dim mStatus As TrafficLightStatus = TrafficLightStatus.statusGreen
Dim msngBorderWidth As Single = 1.0!
Public Event StatusChanged(ByVal NewStatus As TrafficLightStatus)

Las dos variables de las dos primeras líneas proporcionan espacio para almacenar los valores de las propiedades Status y BorderWidth y también establecen el valor predeterminado para dichas propiedades. La variable utilizada para almacenar BorderWidth deberá ser de tipo Single, ya que es el tipo necesario para la instrucción de gráficos que dibujará el borde. El signo de exclamación en el valor predeterminado también indica que es de tipo Single. La última línea de este conjunto declara el evento StatusChanged.

Introduzcamos ahora el código para la propiedad BorderWidth. Inserte las líneas siguientes justo debajo de la sección de código etiquetada como Código generado por el Diseñador de Windows Forms :

<DefaultValue(1.0!), _
Description("Width of the border around the traffic light")> _
Public Property BorderWidth() As Single
    Get
        Return msngBorderWidth
    End Get
    Set(ByVal Value As Single)
        If msngBorderWidth <> Value Then
            msngBorderWidth = Value
            Me.Invalidate()
        End If
    End Set
End Property

Las dos primeras líneas incluyen atributos con los que se consigue que la propiedad funcione correctamente con el IDE. El atributo DefaultValue permite restablecer el valor de la propiedad en su valor predeterminado en la ventanas Propiedades (posteriormente veremos cómo hacerlo). El atributo Description proporciona el texto que aparecerá en la parte inferior de la ventana Propiedades al seleccionar la propiedad.

El atributo DefaultValue también tiene otras importantes ventajas. Si ubica el control TrafficLight en un formulario y deja el valor de la propiedad BorderWidth con su valor predefinido, el diseñador de formularios no generará ninguna línea de código para establecer el valor de la propiedad. De esta forma, se consigue que actúe como otros controles de Windows Forms. Si examina el código generado por el diseñador para un control típico como TextBox, verá que sólo se incluyen líneas de código para propiedades que no se establecen en sus valores predeterminados. Daremos a nuestro control TrafficLight esta misma capacidad.

La cláusula Property Get es simple. La cláusula Property Set incluye una lógica que suele encontrarse en propiedades de controles visuales. Al establecer la propiedad, es importante que el control se vuelva a dibujar si el nuevo valor de la propiedad cambia la apariencia del control. Por tanto, la cláusula de Set comprueba si el nuevo valor que se está pasando es diferente al valor existente en la propiedad. Si no es así, no se lleva a cabo ninguna acción. Si el nuevo valor es diferente, se acepta y, a continuación, se obtiene acceso al método Invalidate. Este método indica que el área visual del control es obsoleta y que se debe volver a dibujar el control.

La propiedad Status debe establecerse de forma ligeramente diferente, ya que es un valor enumerado. El atributo DefaultValue no otorga a una propiedad enumerada la capacidad de restablecimiento automático. En este caso, DefaultValue no indica al diseñador cuándo no debe incluir el código que establece el valor de la propiedad. De esta forma, nuestra implementación de la propiedad Status omite el atributo DefaultValue . A continuación se muestra el código de la propiedad Status:

<Description("Status (color) of the traffic light")> _
Public Property Status() As TrafficLightStatus
    Get
        Status = mStatus
    End Get
    Set(ByVal Value As TrafficLightStatus)
        If mStatus <> Value Then
            mStatus = Value
            RaiseEvent StatusChanged(mStatus)
            Me.Invalidate()
        End If
    End Set
End Property

Este código se asemeja bastante a la implementación de la propiedad BorderWidth, aunque hemos agregado algo. Cuando se cambia la propiedad Status, se desencadena el evento StatusChanged además de forzar que el control se vuelva a dibujar.

Para controlar el restablecimiento automático de la propiedad en la ventana Propiedades, necesitamos un método especial. Como la propiedad se llama Status, el nombre del método de restablecimiento debe ser ResetStatus. Este método simplemente devuelve a la propiedad su valor predeterminado. Éste es el código:

Public Sub ResetStatus()
    Me.Status = TrafficLightStatus.statusGreen
End Sub

Para avisar al diseñador de cuándo debe incluir una línea de código para establecer la propiedad Status, necesitamos incluir un método denominado ShouldSerializeStatus. Este método devuelve un valor booleano True cuando se necesita una línea de código para la propiedad y False cuando no es así. Éste es el código:

Public Function ShouldSerializeStatus() As Boolean
    If mStatus = TrafficLightStatus.statusGreen Then
        Return False
    Else
        Return True
    End If
End Function
Paso 4: dibujo de la apariencia del control

Para dar al control una representación visual, es necesario incluir una lógica en el evento Paint. Dicha lógica se ejecutará cada vez que se tenga que actualizar la apariencia visual del control.

En Windows Forms, la lógica de Paint utiliza clases en la parte de .NET denominada GDI+. Básicamente, estas clases son contenedores de las funciones gráficas de la API de Windows. En .NET, son más fáciles de usar que la API. Sin embargo, hay varios puntos que debería tener en cuenta para comprender su funcionamiento.

En la API de Windows, las operaciones gráficas necesitan un identificador de ventana, denominado a veces hWnd. En GDI+, este identificador se sustituye por el objeto Graphics, que al mismo tiempo representa el área de dibujo y ofrece operaciones (métodos) para realizar en dicha área.

Por ejemplo, con el objeto Graphics se pueden utilizar los siguientes métodos para dibujar diversos elementos de la pantalla:

  • DrawCurve
  • DrawEllipse
  • DrawLine
  • DrawPolygon
  • DrawRectangle
  • DrawString
  • FillEllipse
  • FillPolygon

Estos métodos son muy fáciles de entender y representan sólo una muestra de los métodos disponibles. Algunos métodos más complejos permiten, por ejemplo, girar objetos. Utilizaremos el método DrawRectangle para dibujar el borde y el método FillEllipse para dibujar los círculos de colores.

La mayor parte de los métodos de dibujo necesitan un objeto Pen o Brush. Un objeto Pen se utiliza para dibujar una línea y determinar el color y grosor de ésta. Un objeto Brush se usa para rellenar regiones y determinar el color utilizado en el relleno, así como otros efectos especiales como, por ejemplo, el relleno de la región con un mapa de bits. Utilizaremos un efecto Brush especial para sombrear el color de las luces que no estén encendidas.

A continuación, se muestra el código que supervisa el evento Paint del control:

Protected Overrides Sub OnPaint(ByVal pe As _ 
                        System.Windows.Forms.PaintEventArgs)
    MyBase.OnPaint(pe)

    Dim grfGraphics As System.Drawing.Graphics
    grfGraphics = pe.Graphics

    ' Dibujar primero tres círculos para las luces.
    ' Uno estará "encendido". Los demás estarán sombreados. 
    DrawLight(TrafficLightStatus.statusGreen, grfGraphics)
    DrawLight(TrafficLightStatus.statusYellow, grfGraphics)
    DrawLight(TrafficLightStatus.statusRed, grfGraphics)

    ' Dibujar ahora el contorno del semáforo.
    ' Se necesita un lápiz para dibujarlo. Será negro.
    Dim penDrawingPen As New _
     System.Drawing.Pen(System.Drawing.Color.Black, msngBorderWidth)

    ' Dibujar el contorno del semáforo en el control. 
    ' Definir primero el rectángulo que se va a dibujar. 
    Dim rectBorder As System.Drawing.Rectangle

    rectBorder.X = 1
    rectBorder.Y = 1
    rectBorder.Height = Me.Height - 2
    rectBorder.Width = Me.Width - 2
    grfGraphics.DrawRectangle(penDrawingPen, rectBorder)

    ' Eliminar los objetos de dibujo
    penDrawingPen.Dispose()
    grfGraphics.Dispose()

End Sub

En primer lugar, se otorga a la clase base la capacidad de pintar y básicamente pintará el fondo con el color correspondiente del control. A continuación, el objeto Graphics del control se obtiene de los argumentos del evento.

Posteriormente, se utiliza una función para dibujar cada uno de los tres círculos. Más adelante trataremos esta función. Observe que debemos pasar a la función una referencia del objeto Graphics, junto con una indicación del círculo que queremos dibujar (rojo, amarillo o verde).

A continuación está el código para dibujar el contorno. Se declara un rectángulo con una posición y tamaño adecuados y, a continuación, se pasan al método DrawRectangle del objeto Graphics.

Finalmente, los objetos del dibujo tienen activado el método Dispose. Con GDI+, conviene eliminar los objetos de dibujo en cuanto haya terminado con ellos. De esta manera se limpian los recursos utilizados por el sistema operativo para dibujar. Si el control se va a utilizar en Windows® 98 o Windows Millennium Edition, es muy importarte controlar los recursos gráficos, ya que estos sistemas operativos tienen menos capacidad para dichos recursos.

A continuación se muestra la función que dibuja los círculos:

Private Sub DrawLight(ByVal LightToDraw As TrafficLightStatus, _
                      ByVal grfGraphics As Graphics)

    Dim nCircleX As Integer
    Dim nCircleY As Integer
    Dim nCircleDiameter As Integer
    Dim nCircleColor As Color

    ' Buscar la coordenada X y el diámetro de todos los círculos
    nCircleX = CInt(Me.Size.Width * 0.02)
    nCircleDiameter = CInt(Me.Size.Width * 0.96)
    Select Case LightToDraw
        Case TrafficLightStatus.statusRed
            If LightToDraw = Me.Status Then
                nCircleColor = Color.OrangeRed
            Else
                nCircleColor = Color.Maroon
            End If
            nCircleY = CInt(Me.Size.Height * 0.01)
        Case TrafficLightStatus.statusYellow
            If LightToDraw = Me.Status Then
                nCircleColor = Color.Yellow
            Else
                nCircleColor = Color.Tan
            End If
            nCircleY = CInt(Me.Size.Height * 0.34)
        Case TrafficLightStatus.statusGreen
            If LightToDraw = Me.Status Then
                nCircleColor = Color.LimeGreen
            Else
                nCircleColor = Color.ForestGreen
            End If
            nCircleY = CInt(Me.Size.Height * 0.67)

    End Select
    Dim bshBrush As System.Drawing.Brush
    If LightToDraw = Me.Status Then

        bshBrush = New SolidBrush(nCircleColor)
    Else
        bshBrush = New SolidBrush(Color.FromArgb(60, nCircleColor))
    End If

    ' Dibujar el círculo para la luz de la señal
    grfGraphics.FillEllipse
(bshBrush, nCircleX, nCircleY, nCircleDiameter, nCircleDiameter)

    ' Eliminar el pincel
    bshBrush.Dispose()

End Sub

Éste es el único dibujo complejo del control. Se dibuja una elipse en GDI+ mediante la especificación de las coordenadas X e Y de la esquina superior izquierda del rectángulo, donde se colocará la elipse, y la altura y anchura de dicho rectángulo. Se darán los nombres nCircleX y nCircleY a las coordenadas X e Y, respectivamente. Puesto que estamos dibujando un círculo, la altura y la anchura del rectángulo serán la misma y la variable nCircleDiameter se utilizará para incluir dicho valor.

nCircleX se establece para que se sitúe justo dentro del control (la anchura del control multiplicada por 0,02). La variable nCircleY depende de la luz que se está dibujando y se establece para que se sitúe cerca de la parte superior del control (para la luz roja), a un tercio (para la luz amarilla) o aproximadamente a dos tercios (para la luz verde). El diámetro, nCircleDiameter, se establece al 96% de la anchura del control.

Lo único que falta para dibujar una elipse rellena es seleccionar el color que deseemos utilizar. Determinaremos el color en función de (1) la luz que estemos dibujando y (2) si la luz que estamos dibujando está encendida. Los colores de la luz activa deben tener más brillo que los de la luz inactiva.

El color se utiliza para crear un pincel para el dibujo. Si la luz que se está dibujando está activa, el color se utilizará tal cual. Sin embargo, si la luz está inactiva, se utilizará otra forma para crear una instancia del pincel. A continuación se muestra la línea de código para un pincel de luz inactiva:

bshBrush = New SolidBrush(Color.FromArgb(60, nCircleColor))

Éste no es uno de los mejores nombres de métodos dados en .NET, pero el método FromArgB crea un pincel que sombrea el color mediante su combinación con el color de fondo. El número utilizado como primer argumento está comprendido entre 0 y 255 y, cuanto menor sea, más se fundirá con el fondo. Vamos a usar un valor de 60, que atenuará considerablemente el color de la luz inactiva. Puede probar con valores diferentes para este argumento (o convertirlo en propiedad configurable) para obtener distintos efectos.

Finalmente, el método DrawEllipse del objeto Graphics dibuja el círculo y se completa la función. Recuerde que se llama a la función tres veces, una para cada círculo.

Paso 5: cómo hacer que el control responda al usuario

Para que el usuario pueda cambiar el color de la luz, se deben detectar los clics que realice. Para ello, existen varios medios, como cualquier programador con experiencia en Visual Basic sabe. Utilizaremos uno de los más simples, que consiste en detectar el evento MouseUp. A continuación se muestra el código que detecta el clic del usuario y cambia la propiedad Status de forma adecuada:

Private Sub TrafficLight_MouseUp(ByVal sender As Object, _
                     ByVal e As System.Windows.Forms.MouseEventArgs)_
                     Handles MyBase.MouseUp
    Dim nMidPointX As Integer = CInt(Me.Size.Width * 0.5)
    Dim nCircleRadius As Integer = nMidPointX
    If Distance(e.X, e.Y, nMidPointX, CInt(Me.Size.Height / 6)) _ 
                < nCircleRadius Then
        Me.Status = TrafficLightStatus.statusRed
        Exit Sub
    End If
    If Distance(e.X, e.Y, nMidPointX, CInt(Me.Size.Height / 2)) _ 
                < nCircleRadius Then
        Me.Status = TrafficLightStatus.statusYellow
        Exit Sub 
    End If
    If Distance(e.X, e.Y, nMidPointX, CInt((5 * Me.Size.Height)/6))_ 
                < nCircleRadius Then
        Me.Status = TrafficLightStatus.statusGreen
    End If

End Sub

Private Function Distance(ByVal X1 As Integer, _ 
                          ByVal Y1 As Integer, _ 
                          ByVal X2 As Integer, _ 
                          ByVal y2 As Integer) As Integer
    Return CInt(System.Math.Sqrt((X1 - X2) ^ 2 + (Y1 - y2) ^ 2))
End Function

El control de eventos es bastante simple. Se comprueba la distancia entre la ubicación del clic del mouse y el centro de cada círculo. Observe que los centros de los círculos estarán a 1/6, 1/2 y 5/6 de la extensión total del control, respectivamente. Si aún no lo ve claro, dibújelo en un papel para comprobarlo. Si la distancia calculada es inferior al radio del círculo, se cambiará la propiedad Status.

La función Distance calcula la distancia mediante una fórmula algebraica que probablemente conocerá. Observe que la función para calcular la raíz cuadrada se toma del espacio de nombres System.Math, en el que se encuentran las funciones matemáticas típicas.

Paso 6: limpieza

Para que el control funcione sin problemas, se deben controlar un par de operaciones más. Por ejemplo, es necesario volver a dibujar el control cuando cambie de tamaño. Además, para mantener las proporciones del control, se deben detectar los cambios en las propiedades que afectan al tamaño y forzar que la anchura sea un tercio de la altura. A continuación se muestran las rutinas para el control de eventos a cargo de estas tareas:

Private Sub TrafficLight_Resize(ByVal sender As Object, _
                 ByVal e As System.EventArgs) Handles MyBase.Resize
    Me.Invalidate()
End Sub

Private Sub TrafficLight_Layout(ByVal sender As Object, _
             ByVal e As System.Windows.Forms.LayoutEventArgs) _
             Handles MyBase.Layout
    Select Case e.AffectedProperty
        Case "Bounds"
            Me.Width = CInt(Me.Height * 0.3333)
        Case Else
            ' No hacer nada
    End Select
End Sub

Finalmente, veamos el icono que se utilizará en el cuadro de herramientas. El control ya dispone de un icono predeterminado que se parece a un engranaje, pero utilizaremos otro que proporciona Visual Studio .NET que representa un semáforo.

El icono del cuadro de herramientas de un control se establece con un atributo de la clase denominada ToolboxBitmap. Inserte la siguiente línea a continuación de la línea que comienza por Public Class :

<ToolboxBitmap("C:\Archivos de programa\Microsoft Visual Studio 
.NET\Common7\Graphics\icons\Traffic\TRFFC09.ICO")> _

Nota   Este código debe incluirse en una sola línea, se ha insertado un retorno de carro después de Studio para facilitar su lectura. Cuando pegue este código, asegúrese de que se encuentra en una sola línea, de que hay un único espacio entre Studio y .NET y de que se ha eliminado el retorno de carro. De esta forma, se establecerá el atributo en un icono ubicado en el directorio de Visual Studio para el atributo, suponiendo que ha instalado Visual Studio .NET en la ubicación predeterminada. Si no es así, cambie la ruta al icono según corresponda.

Paso 7: generación y prueba del control

El control TrafficLight ya está terminado. Seleccione Generar | Generar MyControls para crear la biblioteca de controles terminada.

Para probar el control, necesitaremos un proyecto de Windows Forms. Para ello, puede utilizar una solución independiente, aunque es más fácil hacerlo en la misma solución utilizada para desarrollar el control. Seleccione Archivo | Agregar proyecto | Nuevo proyecto en el menú. Seleccione el tipo de proyecto Aplicación para Windows e introduzca TestTrafficLight como nombre del proyecto. Haga clic en Aceptar para que la aplicación para Windows realice la prueba.

Para poder arrastrar un control TrafficLight a Form1 en blanco para la aplicación de prueba, antes necesitará agregar el control TrafficLight al cuadro de herramientas. Haga clic con el botón secundario en la ficha de Windows Forms del cuadro de herramientas y seleccione Personalizar cuadro de herramientas. Seleccione la ficha Componentes de .NET Framework y, a continuación, haga clic en el botón Examinar. Busque la ubicación del proyecto MyControls y, a continuación, el directorio /bin del proyecto. Seleccione el componente MyControls.dll y haga clic en Aceptar. El cuadro de diálogo debería ser similar al que se muestra en la figura 2.

Figura 2. Selección del control TrafficLight en el cuadro de diálogo Personalizar cuadro de herramientas.

Observe que junto al control TrafficLight hay una marca de verificación. Haga clic en el botón Aceptar. El control TrafficLight aparecerá ahora al final de la lista de controles de la ficha Windows Forms del cuadro de herramientas. En la figura 3 se muestra un cuadro de herramientas con el control TrafficLight situado al final.

Figura 3. Control TrafficLight al final de Toolbox

Ahora, puede arrastrar un control TrafficLight a Form1 en blanco en TestTrafficLight. De forma predeterminada, su nombre será TrafficLight1. Puede cambiar el tamaño del control y establecer sus propiedades, incluida la propiedad Status, que dispondrá de un menú desplegable con los tres posibles valores para dicha propiedad. Observe que a medida que cambia el tamaño o las propiedades, el control se actualiza automáticamente en el diseñador.

Para ver el restablecimiento de una propiedad en su valor predeterminado, cambie la propiedad Status a statusRed. A continuación, haga clic con el botón secundario en la propiedad Status de la ventana Properties y seleccione Reset, como se muestra en la figura 4. La propiedad volverá a cambiar a statusGreen. El truco del restablecimiento también funciona con la propiedad BorderWidth si se establece en un valor distinto de 1.

Figura 4. Opción Restablecer para la propiedad Status en la ventana Propiedades. Observe la descripción de la propiedad Status en la parte inferior de la ventana.

Si lo desea, también puede insertar un evento StatusChanged para el control. A continuación, podrá ver el estado modificado con esta línea de código en dicho evento:

MsgBox("New status is " & 
NewStatus.ToString)

Para para realizar una prueba del control en plena acción, tendrá que iniciar el proyecto TestTrafficLight. En este momento, no es el proyecto de inicio de la solución, así que tendrá que solucionarlo. En el Explorador de soluciones, haga clic con el botón secundario en el nombre Solution, en la primera fila. Seleccione Propiedades y, a continuación, cambie la configuración Proyecto de inicio único de MyControls a TestTrafficLight. Haga clic en Aceptar.

Presione F5 para iniciar el proyecto. Aparecerá el formulario con el control TrafficLight. Para probar el control, presione diferentes luces y observe cómo se encienden. También puede realizar una prueba de la propiedad BorderWidth e intentar establecer la propiedad Status de la luz en el código.

Conclusión

Hay que admitir que el control TrafficLight es simple, aunque conocí a un programador que lo necesitó para un proyecto real. Sin embargo, muestra todos los principios necesarios para desarrollar controles más sofisticados, entre los que se incluyen:

  • La adición de propiedades al control
  • La posibilidad de que las propiedades se puedan coordinar con el IDE de Visual Studio mediante valores y descripciones predeterminados
  • La inserción de una lógica en el evento Paint para dibujar el control
  • El uso de GDI+ en la lógica de dibujo
  • El establecimiento de un mapa de bits para que el control se muestre en el cuadro de herramientas

La clave para crear controles más sofisticados es familiarizarse con las capacidades de dibujo de GDI+. Si comprende cómo TrafficLight dibuja su contorno y los círculos de colores, es un buen punto de partida. La idea principal es que incluso los programadores perezosos como yo pueden crear controles de Windows Forms avanzados con Visual Basic .NET.

comentarios
  1. Daniel dice:

    Muchas gracias, hace tiempo que vengo buscando un manual como este, ya que quiero crear mis propios controles.
    De hecho me va ha servir de mucho.

    • Oswaldo dice:

      Por fin aclaré mis dudas con respecto a la creación de un control. Muy bueno este material para mí tienes un 10 en la escala del 1 al 10.

  2. Jaime dice:

    Excelente guia para la creacion basica de controles, lástima que no aparezcan las imágenes para mayor entendimiento.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s