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
Studiopara 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 entreStudioy.NETy 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.
Archivado en: Categoria All
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.