Como Crear tu Propio Control ActiveX

Siguiendo con la norma de entregar ejemplos prácticos y simples que permitan entender los conceptos básicos de programación VB presento aquí la creación de un control ActiveX . De los varios libros y ejemplos en la www sobre el tema no encontré ninguno lo suficientemente claro para un principiante, así es que hice uno yo mismo. Espero que este les sirva y sea de provecho para los que se interesan por esta poderosa característica de Visual Basic

 

La Ventaja de los Componentes
Los componentes son la extensión de la idea de las subrutinas, las funciones y los módulos de clase, se trata de tener módulos de propósito general codificados y empquetados en un "componente" con métodos y propiedades de modo que podamos usarlo en distintas aplicaciones que programemos

Los controles ActiveX son los sucesores de los antiguos controles vbx y aparecen en la caja de herramientas del Visual Basic, por ejemplo los textbox, combobox, listbox, labels, etc. A diferencia de los vbx antiguos que solo podían ser creados usando C++, el usuario puede hoy crear sus propios controles ocx y programarlos en el propio Visual Basic.

 

Tipos de Componentes que Podemos Programar
Podemos crear un componente que sea visible en tiempo de ejecución (como los textbox o los listbox por ejemplo) o bien uno invisible, es decir sin interfaz de usuario.

Podemos modificar un control existente agregándole nuevas funcionalodades (por ejemplo crear un textbox mejorado que tenga una propiedad llamada "tipo" que cuando esté en 0 acepte  toda clase de caracteres, cuando este en 1 acepte solo números, cuando esté en 2 acepte solo letras, cuando esté en 3 ingrese el formato de fechas, etc.)

También podemos combinar varios controles para crear uno nuevo (por ejemplo creando un control que consista en una pantalla de ingreso de datos)

Finalmente podríamos incluso dibujar un control comletamente nuevo a partir de cero, con su interface y propiedades.

De todas estas alternativas yo creo que las más útiles para un usuario corriente son crear un control combinando otros ya existentes y agregarle funcionalidades "a nuestra medida" a un control que ya existe. En lugar de los controles invisibles yo prefiero usar módulos de clase o dll compiladas y diseñar un control a partir de cero creo que sirve más que nada para fines académicos, las principales aplicaiones prácticas ya están en su mayoría implementadas.

 

Planificando un Control
La parte difícil de todo esto es encontrar una buena idea de control para implementar. En el siguiente ejemplo supondremos que hay una ventana para ingresar datos personales que podríamos usar en varios programas distintos. Así, el control que haremos creará la clásica ventana de ingreso de nombre, dirección y teléfono,  de este aspecto:

Ya hemos hecho la primera parte, que es el diseño de la interfase que verá el usuario, ahora nos falta darle propiedades y métodos a nuestro control. Para no alargar mucho el asunto le daremos una sola propiedad llamada strSalida que almacenará los datos ingresados en un string con campos de largo fijo: 30 para el nombre, 30 para la dirección y 10 para el teléfono

El primer paso es elegir Archivo, Nuevo Proyecto, Control ActiveX, aparecerá una pantalla similar a un form pero sin bordes

Luego cambiamos la propiedad del nombre de UserControl1 a IngresoCtl

Elegimos Proyecto, Propiedades de Ingreso y cambiamos el nombre de Proyecto1 a (por ejemplo) Ingreso, la propiedad Public debe ponerse en True. Cerramos la ventana de propiedades del proyecto

Agregamos un frame (marco de fondo) y los tres textbox a los cuales les ponemos los nombres de txtTexto1, txtTexto2 y txtTexto3 respectivamente (por si no lo habían notado antes, la ventaja de definir nombres con mayúsculas y minúsculas combinadas es que después seguimos escribiendo los nombres en minúsula y si no cambia la caja nos damos cuenta inmediatamente que escribimos mal el nombre)

 Después agregamos los lbl1, lbl2 y lbl3 con los valores caption correspondientes y grabamos

 

Escribiendo el Código
¿Han notado que los controles ActiveX cambian de tamaño arrastrando los bordes con el cursor?. Bueno hay algunas líneas de código que se deben agregar al evento Resize para asegurarse que los controles dentro del ocx no queden ocultos al usuario o fuera de la acción de su mouse. En nuestro ejemplo el código sería el siguiente:


Private Sub UserControl_Resize()
     With UserControl
          If .Height < 3615 Then .Height = 3615
          If .Width < 2175 Then .Width = 2175
          TxtTexto1.Width = .ScaleWidth - 500
          TxtTexto2.Width = .ScaleWidth - 500
          TxtTexto3.Width = .ScaleWidth - 500
     End With
End Sub

Donde las líneas

           If .Height < 3615 Then .Height = 3615
           If .Width < 2175 Then .Width = 2175

Aseguran que el control tendrá siempre las dimensiones mínimas de ancho y alto, mientras que las líneas:

           TxtTexto1.Width = .ScaleWidth - 500
           TxtTexto2.Width = .ScaleWidth - 500
           TxtTexto3.Width = .ScaleWidth - 500

Cambian el tamaño de los textboxes de acuerdo con el tamaño total del control

 

Agregando la Propiedad al Control
Para pasarle propiedades al control desde el programa usamos una función Public Property Let, para que el control entregue propiedades al programa usamos Public Property Get.

Por ejemplo podría agregar propiedades al control para cambiar el título del frame y los caption de las label que van arriba de cada textbox. Así el control me serviría no solo para ingresar nombre, dirección y teléfono sino que podríamos usar otros rótulos cualquiera, para esto escribimos en el control los siguientes procedimientos:

Public Property Let Titulo(tit)
      Frame1.Caption = tit
End Property

Public Property Let Leyenda1(Ley1)
       Lbl1.Caption = Ley1
End Property

Public Property Let Leyenda2(Ley2)
        Lbl2.Caption = Ley2
End Property

Public Property Let Leyenda3(Ley3)
         Lbl3.Caption = Ley3
End Property


¡Y ya tenemos definidas nuestras primeras cuatro propiedades que podemos cambiar desde el programa en donde colocaremos el control!

También podemos definir una propiedad de salida, es decir algo que haga el control con los datos ingresados, en este caso haremos un solo string con los tres ingresos dejándolos de largo fijo con 30, 30 y 15 caracteres respectivamente, esto se puede hacer así

Public Property Get StrSalida() As String
         Dim Salida As String
         blancos = Space(30)
         Txt1 = Mid(TxtTexto1.Text + blancos, 1, 30)
         Txt2 = Mid(TxtTexto2.Text + blancos, 1, 30)
         Txt3 = Mid(TxtTexto3.Text + blancos, 1, 15)
         Salida = Txt1 & Txt2 & Txt3
         StrSalida = Salida
End Property

El resultado será siempre un string de 75 caracteres de largo, los primeros 30 para el nombre, a partir del 31 con la dirección y desde el 61 irá el teléfono, lo que sobre se llenará con espacios en blanco (así se formaban los registros en los sistemas de archivo primitivo, puse el ejemplo de pura nostalgia)

Ya estamos casi listos, solo falta dar unas "manitos de gato" para que nuestro primer control ocx nos quede operativamente decente, por eso agregamos código para que el foco se desplace hacia abajo cada vez que coloquemos Enter con

Private Sub TxtTexto1_KeyPress(KeyAscii As Integer)
      If KeyAscii = 13 Then
           TxtTexto2.SetFocus
      End If
End Sub


Private Sub TxtTexto2_KeyPress(KeyAscii As Integer)
         If KeyAscii = 13 Then
             TxtTexto3.SetFocus 
         End If
End Sub

Y finalmente colocamos un color de fondo mas resaltado, el control ocx está listo y nos ha quedado más o menos así:

Grabar, Compilar y Probar el Control
Ya estamos listos, solo nos queda grabar, compilar y probar. Para compilar usamos Archivo, Generar dirección ocx.. Para probar el control simplemente abrimos un nuevo proyecto Exe estándar, nos vamos a Proyecto, Componentes y examinar, y cargamos nuestro ocx desde el lugar donde lo grabamos (el directorio donde estábamos trabajando al generarlo).

Al poner Aceptar aparecerá nuestro flamante ocx en la barra de herramientas, para probarlo simplemente lo colocamos en el form y si todo está Ok nos saldrá algo así como esto:

Fíjense que además agregué al formulario un botón con el caption "Test" y un label en la parte de abajo. El botón mostrará el string entregado por el control con los datos que ingresamos. Para darle propiedades al control en el evento load() puse:

Private Sub Form_Load()
        IngresoCtl1.Titulo = "Ingrese los Datos"
        IngresoCtl1.Leyenda1 = "Nombre"
        IngresoCtl1.Leyenda2 = "Dirección"
        IngresoCtl1.Leyenda3 = "Teléfono"
End Sub

Y en el evento click() del botón command1 el código que puse es:

Private Sub Command1_Click()
           Label1.Caption = IngresoCtl1.StrSalida
End Sub

Si funcionó todo Ok me imagino que estarán muy contentos con su primer control ActiveX "homemade".  Pero...

 

¿Y si algo no Funciona?
Uno de los pocos problemas que encontré en esto de crear controles ActiveX es la depuración del programa. Para depurar parece que la manera más práctica (la única que se me ocurrió por lo demás) es, en el mismo proyecto donde programamos el control ActiveX colocar Archivo, Agregar Proyecto, Exe Estándar. Con esto queda un grupo de proyectos formado por el ActiveX propiamente tal y un Proyecto exe donde podemos colocar un form e ir probando nuestro control. En´este punto tuve algunos problemas como que al ejecutar el proyecto de prueba de pronto me aparecía el control dentro del Explorer, o que el equipo se quedaba sin memoria, bueno el caso que después de algunos tropiezos me acostumbré, pero les recomiendo que traten de que les quede bien a la primera porque el proceso de depuración es más o menos raro.

 

Créditos

El ejercicio presentado aquí lo hice con la ayuda del libro "Edición Especial, Visual Basic 6.0" de Brian Siler y Jeff Spotts, Editorial QUE (949 pgs)