Infografías de ActiveX
Bienvenidos a la página Web de Alirio Jeanton

Infografía


ActiveX7
http://www.mvps.org/vexpert/articles/axProp1.htm
http://www.mvps.org/vexpert/articles/axProp2.htm

Extendiendo Controles con ActiveX

Parte 1

Creando Controles ActiveX para Extender las Propiedades de un Control Estándar

Como yo, pienso que alguna vez Usted se cansa de escribir procedimientos para dar una mayor funcionalidad a los Controles Visual Basic, y repetir una y otra vez el código en sus proyectos. Un ejemplo clásico es aquello de que cuando un TextBox gane el enfoque aparezca seleccionado su contenido. Yo ideé un módulo independiente Bas para que los TextBox se comporte como yo quiero, y llamo a los procedimientos desde los eventos, pasando como parámetro el TextBox. -¡ Que aburrido !, repita y repita llamadas para cada TextBox o arreglo de TextBox que agregue a un Formulario. La solución era perfectamente aceptable hasta Visual Basic nos entrego ActiveX de una manera flexible. Así pues, aprovechemos ActiveX, donde simplemente escribo un Control ActiveX para extender propiedades a TextBox y listo. Bastará dibujar el control en los formulario y asignarle propiedades para obtener toda la funcionalidad programada. Es como si Visual Basic me entregara el control tal y como lo quiero.

Ejemplo para Extender Propiedades y Métodos a Controles
Primero que todo, advierto que este articulo no es un manual para crear controles ActiveX, es un paso más halla para explicar ciertos detalles prácticos de programación. Si desea un documento que le enseñe desde cero, recomiendo los temas "Generación de Controles ActiveX" y "Creación de un Control ActiveX" de los Libros en Pantalla de VB5.
El postulado del ejemplo es el siguiente: deseamos crear más propiedades en un TextBox, para empezar, SelectOnGotFocus, selección automática del texto al ganar enfoque, y OnlyNumber, para aceptar solo números cuando es True. Esto es supremamente fácil para un programador experimentado, pero éste es inquieto y quiere algo más, quiere enterrar la repetición de las líneas de código o la llamada a un procedimiento.

¿Cómo empezar?
Este resumen le refrescará la memoria para la creación de un Control ActiveX:
· Cree un Proyecto EXE estándar.
· Agregue un Proyecto Control ActiveX.
· Especifique nombres a Proyecto1, Form1, Proyecto2, UserControl1. El nombre del archivo que contiene UserControl1 será el nombre del OCX, por favor cambie UserControl1.clt. La propiedad Name de UserControl1 será el nombre de la clase de su control.
· Diseñe y escriba el nuevo Control en el diseñador de UserControl.
· Cuando este listo y completamente depurado compile como OCX.

Directo al Código
Abra el diseñador de UseControl1 y agregue un TextBox. Daré una explicación a cada procedimiento agregado.
Primero, automatizaremos el ajuste de los tamaños del Control y el Textbox:

Private Sub UserControl_Resize()
Height = Text1.Height '//La altura del Control ajustada al TextBox
Text1.Move 0, 0, ScaleWidth '//Ancho del TextBox ajustado al Control
End Sub

El código para extender una propiedad a un Control, siguiendo el ejemplo para la nueva propiedad OnlyNumber, sigue estas directrices: En la sección declaraciones se crea la variable m_OnlyNumbers que mantendrá el valor local de la propiedad. Si no lo sabia, el prefijo "m_" es una convención de la programación orientada a objetos y significa "member"; hasta donde sé, se usa en C++, Java, y Visual Basic.

Option Explicit
Private m_OnlyNumbers As Boolean
El siguiente bloque determina la acción que queremos. Text1 activa su Evento KeyPress desde el Control de usuario pero el usuario no tendrá acceso a este evento puesto que es privado del módulo UserControl1.ctl. No es necesario extender el evento, pero se puede hacer si quisiera. Cuando OnlyNumbers se especifique a True en tiempo de diseño o ejecución del usuario del Control, solo serán permitidos caracteres numéricos, punto y signo menos como entradas.
Private Sub Text1_KeyPress(KeyAscii As Integer)
If m_OnlyNumbers Then
If InStr("-.0123456789", Chr(KeyAscii)) = 0 Then
KeyAscii = 0
Beep
End If
End If
End Sub

Es común la asignación de valores predeterminados a las propiedades. Cuando un usuario coloca el control en un formulario estas propiedades aparecen en la ventana de diseño Propiedades.
Private Sub UserControl_InitProperties()
m_OnlyNumbers = False
End Sub

Los dos siguientes procedimientos son la clave para que el formulario del diseñador (usuario de su control) reconozca las propiedades cuando se cierra el proyecto y se vuelve a abrir. Como abra notado, el código de un formulario contiene una definición de los controles y sus propiedades en su encabezado, pues es allí donde precisamente leerá y escribirá el objeto UserControl.

'//Cargar valores de propiedades desde el almacenamiento
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
m_OnlyNumbers = PropBag.ReadProperty("OnlyNumbers", False)
End Sub

'// Escribir valores de propiedades en el almacenamiento
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
PropBag.WriteProperty "OnlyNumbers", m_OnlyNumbers, False
End Sub
Los dos procedimientos siguientes son ampliamente conocidos por quienes programan clases en VB. Son la propiedad en sí. La línea PropertyChanged "OnlyNumbers" del procedimiento Let permite que el objeto UserControl le avise al formulario que la propiedad OnlyNumbers y la coloque en la ventana a Propiedades del diseño del proyecto del usuario.
Public Property Get OnlyNumbers() As Boolean
OnlyNumbers = m_OnlyNumbers
End Property

Public Property Let OnlyNumbers(ByVal New_OnlyNumbers As Boolean)
m_OnlyNumbers = New_OnlyNumbers
PropertyChanged "OnlyNumbers"
End Property Terminamos. Esta es la "receta" para galletas con chocolate. Si le pareció extenso, no se preocupe, VB incorpora el complemento "Asistente para Interfaz Control ActiveX" que le facilitará enormemente el trabajo. Es muy simple de usar, seleccione el complemento, Siguiente, Siguiente, Nuevo, escriba el nombre de la propiedad (el botón de radio debe editar en propiedad), llene el cuadro de dialogo (tipo, etc.) y Terminar. Automáticamente crea las líneas de código, prácticamente iguales a como las presente en esta discusión, quizá requiera de algunos retoques para agregar funcionalidad o quitar código innecesario (por ejemplo la variable para establecer un valor predeterminado a una propiedad bolean no es requerida)

Exposición de las Propiedades del Control Componente
Por supuesto, Usted va a querer que la propiedad Text del Text1 este disponible. Malas, ¿o buenas? Noticias, tendrán que escribir código para delegar esa propiedad. Tras bambalinas le comento que usamos una técnica para implementa Herencia en VB, es decir, queremos que nuestro control herede la propiedad Text del TextBox. Para no alargar el asunto, bastara con:

Public Property Get Text () As String
Text = Text1.Text
End Property

Public Property Let Text (ByVal New_Text As String)
Text1.Text = New_Text
End Property

No es tan crítico ¿verdad?. Tendrán que agregar más cosas si desea que la propiedad aparezca en el cuadro de dialogo Propiedades. También es muy inteligente usar el complemento "Asistente para Interfaz Control ActiveX" en este caso.

Usar Como Componente
Nunca fue tan fácil hacer un Componente de Software. Simplemente compile como OCX y podrá usar el Control en cualquier aplicación VB5 de su maquina. Si desea llevarlo a otra maquina para diseñar, lo más fácil es llevar el código del ctl y compilarlo allí para no tener problemas de licencia. En otro caso tendrá que crear el software para instalarlo. De otra parte un ejecutable de una aplicación que use su control no tendrá problemas y correrá en cualquier PC, no obstante un PC con VB5 no podrá usar su control para diseño. Para la cuestión de licencias recomiendo el tema "Distribuir los controles" en "Generación de Controles ActiveX" de los Libros en Pantalla de VB5.

Desventajas
No podrá delegar una propiedad de solo lectura a los usuarios de su control. Por ejemplo la propiedad MultiLine siempre será la que especifico en su control. Esto se debe a que la propiedad tendría que ser asignada con código en el módulo de UserControl, y como esta es de solo lectura no acepta tal operación. Afortunadamente en un OCX podemos colocar varios objetos UserControl. Para usar toda las propiedades (Lectura/Escritura) de TextBox, tendría que delegarlas una por una. En verdad, a modo de discusión, esto no es un verdadero problema ya que cuando Usted programa un control es para que este le preste un servicio a Usted y no necesita delegar todas las propiedades. Por ejemplo nunca voy a necesitar cambiar la Fuente del TextBox. Ahora, si piensa distribuir su control como comercial si tendrá que delegar todas las propiedades, -no le quepa duda, no faltará Mr. Bean que le preguntará ¿y que, no puedo cambiar la Fuente de TextBoxPlus? ; antes de que piense asesinarlo, delegue la propiedad Font. Sin embargo pienso que en una versión futura de Visual Basic podremos extender todas las propiedades con una instrucción. - Sortilegio: Algo como escribir en declaraciones Extends NombreDeClase.

Ventajas
Todas, innumerables, nunca antes los programadores Visual Basic estabamos tan contentos, es una mina, solo denme tiempo y verán lo que puedo hacer. Lo que se hace en C++ con mil constantes y cientos de un código que parece idioma Chino, se puede hacer en un momento con Visual Basic y una pizca de inspiración.
Las principales ventajas que encuentro son: (1) Encapsulamiento de Código, (2) Protección de la autoría de código y, (3) Extensibilidad de Controles. -¿Todavía piensa en Herencia?.
De otra parte, como componente de software, puede colocar su control en páginas HTML y ejecutar en cualquier Browser que apoye ActiveX. ¿Algo más?.

Ejemplo del Articulo
Este ejemplo fue publicado en el Magazín Algoritmo. Abra el grupo de proyectos Test_TXTEXT.vbg y ejecute. En la gráfica se ve en acción mi TextBoxPlus. No es un Control que esté completo para ser usado, su propósito es didáctico, y es un buen ejemplo que puede terminar si lo desea.

TextBoxPlus presenta un elegante relieve (imitado de Access) y una etiqueta que acompaña al TextBox. Esto ultimo fue para quitarme de encima ese problemita de tener que agregar un Label y cuadrar alineación, tamaños, Fondo, Nombre, etc. ¿Me estaré volviendo perezoso?.
La parte 2 de este articulo trata sobre Propiedades Especiales: (1) Delegar una propiedad que suministra Constantes Visual Basic, (2) Delegar una propiedad que suministra cuadros de dialogo estándares, (3) Crear una propiedad con constantes propias, y (4) Dar capacidades de enlace a datos a nuestros Controles ActiveX.

Extendiendo Controles con ActiveX
Parte 2


Propiedades Especiales
En el articulo de Mayo trate sobre las posibilidades de ActiveX para derribar las barreras de la carencia de propiedades personalizadas en los Controles OCX estándares. Es idóneo extender este documento para incluir unos temas de importancia fundamental en este propósito: (1) Delegar una propiedad que suministra Constantes Visual Basic, (2) Delegar una propiedad que suministra cuadros de dialogo estándares, (3) Crear una propiedad con constantes propias, y (4) Dar capacidades de enlace a datos a nuestros Controles ActiveX.

1. Delegar una Propiedad que Suministra Constantes Visual Basic
Propiedades como Alignment, BorderStyle, y muchas otras, suministran una línea de constantes propias. Si su control va a delegar esta propiedad, lo más conveniente y profesional es suministrar al usuario de su control esta interfaz.
Ejemplo: La propiedad Alignment de un control Label suministra estas constantes:

vbLeftJustify = 0
vbRightJustify = 1
vbCenter = 2
Para que su control suministre estas constantes debe escribir un código con esta sintaxis:



Public Property Get LabelAlignment() As AlignmentConstants
LabelAlignment = lbl.Alignment
End Property

Public Property Let LabelAlignment( _
ByVal New_LabelAlignment As AlignmentConstants _
)
lbl.Alignment = New_LabelAlignment
PropertyChanged "LabelAlignment"
End Property
Es claro que no requerimos una variable de miembro (Prívate) para guardar el valor de LabelAlignment, pues la propiedad Alignment del Label nos guarda el valor.
Al declarar la propiedad como AlignmentConstants, Visual Basic la reconoce y en la ventana de propiedades del ambiente de desarrollo mostrará la lista desplegable con las constantes. También dentro de su código, el usuario del control podrá usar las constantes vbLeftJustify, vbRightJustify, y vbCenter sin preocuparse por su valor explícito.
Por ultimo, recordemos que debemos escribir las líneas en los eventos ReadProperties y WriteProperties para que la propiedad sea perecedera para los usuarios que emplean nuestro control:

Prívate Sub UserControl_ReadProperties(PropBag As PropertyBag)

'//Alineamiento del texto en la etiqueta
lbl.Alignment = PropBag.ReadProperty("LabelAlignment", vbRightJustify)
...
End Sub

Prívate Sub UserControl_WriteProperties(PropBag As PropertyBag)
'//Alineamiento del texto en la etiqueta
Call PropBag.WriteProperty( _
"LabelAlignment", lbl.Alignment, vbRightJustify _
)
...
End Sub

En este ejemplo y en los siguientes se uso un control etiqueta (Label) con nombre lbl.

2. Crear una Propiedad con Constantes Propias
En este caso empleamos Enum. Ilustraré esto con un ejemplo. Digamos que su control va a suministrar una propiedad para filtrar las entradas en un TextBox, de acuerdo a si los caracteres digitados se deben pasar a Mayúsculas, Minúsculas, etc.

1. Empezamos por crear un tipo de enumeración con los nombres de las constantes

'//POPERTY: InLetFormat
Public Enum InLetFormatConstants
tbp_None
tbp_OnlyNumbers
tbp_ToUpperCase
tbp_ToLowerCase
tbp_ToSpanishTitle
tbp_ToEnglishTitle
End Enum
El prefijo tbp es simplemente convencional y lo uso para identificar la clase de mi Control (TextBoxPlus). Si desea más detalles de las Enumeraciones sugiero ojear Enum. Generalmente los valores que asigne Enum no nos interesan, pues su objetivo es dar una palabra significativa (para información acerca de la asignación de valores en Enum sugiero consultar la ayuda Visual Basic para Enum).

2. En declaraciones

'//Propiedad de enumeración personalizada:
Prívate m_InLetFormat As InLetFormatConstants
Como en el caso de propiedades estándares que suministran constantes, la declaración As NombreEnumeración, hará que Visual Basic le suministre una lista desplegable al usuario de su control con los nombres de las constantes.

3. Código de la propiedad


'// PROPERTY: InLetFormat
Public Property Get InLetFormat() As InLetFormatConstants
InLetFormat = m_InLetFormat
End Property

Public Property Let InLetFormat( _

)
m_InLetFormat = New_InLetFormat
PropertyChanged "InLetFormat"
End Property

Las acciones que desee implementar a la propiedad corren por su cuenta. En este caso escribí los filtros en los eventos de teclado del TextBox. La siguiente imagen ilustra el efecto.



Propiedades con constantes propias
3. Delegar una Propiedad que Suministra Cuadros de Dialogo Estándares
Propiedades como ForeColor, BackColor, Font, y otras, requieren tratamiento especial. La ventana de propiedades del entorno de desarrollo de Visual Basic muestra cuadros de dialogo estándares para asignar los valores. Para que su control despliegue estos cuadros debe hacer lo siguiente. Ilustraré con la propiedad BackColor de un control cuadro de texto:


'//PROPERTY: TextBackColor
Public Property Get TextBackColor () As OLE_COLOR
TextBackColor = txt.BackColor
End Property

Public Property Let TextBackColor (ByVal NewColor As OLE_COLOR)
txt.BackColor = NewColor
PropertyChanged "TextBackColor"
End Property
Simplemente declaramos la propiedad al tipo OLE correcto. Otras propiedades como Font son objetos y requieren un tratamiento menos sencillo, sin embargo el Asistente para interfaz de controles ActiveX puede reducir considerablemente el trabajo necesario para exponer las propiedades de los controles constituyentes; generalmente lo uso como primer paso y luego le doy la pulida que requieren mis propósitos.

4. Dar Capacidades de Enlace a Datos a los Controles ActiveX
Al final del camino lo importante es que nuestros controles se puedan enlazar a datos. Los controles de usuario no solo permite enlazar un solo campo, se pueden crear múltiples enlaces a datos (por ejemplo el control DBGrid tiene enlaces múltiples a través del objeto Columns). De igual forma que los controles enlazados suministrados con Visual Basic, su control enlazado a datos tendrá una propiedad DataSource y una propiedad DataField. Finalmente para los usuarios de nuestro control, la interfaz Aplicación - Bases de Datos se apoya en un control como Data.
Para una introducción rápida, diré que el enlace se hace a través de una propiedad creada en UserControl, normalmente aquella predeterminada del control componente principal, es decir, por ejemplo si nuestro control delega un TextBox mejorado, la propiedad que se enlazará será Text. Lo primero que haremos es delegar la propiedad Text (en el articulo anterior a este continúe una explicación de la técnica), luego agregamos unas líneas de código, y por ultimo fijamos unos datos en el cuadro de dialogo Menú Atributos de Procedimiento (sección Avanzado). El procedimiento paso a paso lo describo a continuación.

1. Delegar Propiedad que luego tendrá capacidad de enlace


'//------------------------------------------------------------
'// PROPIEDAD TEXT
'//------------------------------------------------------------
Public Property Get Text() As Variant
Text = txt.Text
End Property

Public Property Let Text(NewValue As Variant)
If CanPropertyChange("Text") Then
txt = NewValue
'//Actualizar origen de datos
PropertyChanged "Text"
End If
End Property


2. Agregar líneas de enlace

'//------------------------------------------------------------
'// PROPIEDAD TEXT
'//------------------------------------------------------------
Public Property Get Text() As Variant
Text = txt.Text
End Property

Public Property Let Text(NewValue As Variant)
If CanPropertyChange("Text") Then
txt = NewValue
'//Actualizar origen de datos
PropertyChanged "Text"
End If
End Property

Prívate Sub txt_Change()
'//Actualizar cambios del usuario
PropertyChanged "Text"
End Sub.


3. Fijar datos del cuadro de dialogo Atributos de Procedimiento

Menú Herramientas, Opción Atributos de Procedimiento, comando Avanzado. Seleccione la propiedad enlazada del cuadro desplegable Nombre. Luego indique las casillas del marco Enlace de datos, como se muestra en la siguiente imagen.



Cuadro de dialogo Atributos de Procedimiento
Varias Propiedades Enlazadas
Cuando su control ActiveX se compone de varios controles componentes, y desea darle propiedades de enlace a todos, deberá seguir el procedimiento anterior para cada atributo. Sin embargo, sólo puede asignar una sola propiedad como DataField en el cuadro de diálogo Atributos del procedimiento. Para permitir que se puedan establecer valores para propiedades enlazadas adicionales, tendrá que utilizar la colección DataBindings.
Por cada propiedad enlazada adicional que desee agregar al control, active Mostrar en la colección DataBindings en tiempo de diseño, en la sección Avanzados del cuadro de diálogo Atributos del procedimiento. Puede establecer DataField para propiedades enlazadas adicionales en tiempo de ejecución, mediante código de Visual Basic. Por ejemplo, un control "miControl" con un segundo campo enlazado a datos, "Campo2", se podría crear con el código siguiente: miControl.DataBindings( "Campo2").DataField = "NombreDeCampo".
Si ha creado página de propiedades, en tiempo de diseño, la colección DataBindings aparecerá en la página de propiedades del control. La página de propiedades es aquella que aparece si hace clic en los tres puntos que se encuentran junto a esta propiedad. La creación de las páginas de propiedades son importantes si desea distribuir su control. La documentación VB en Libros en Pantalla trae ejemplos Paso a Paso para crear páginas de propiedades.




[ Principal  ] [  Infografía  ]