|
Un Manejador de Eventos Para VB6 – Parte 2 Una clase que maneje los eventos de componentes ActiveX puede ir mas allá de la directiva Event Por Harvey Triana IntroducciónEn la primera parte de este articulo di a conocer las bondades de un manejador de eventos para VB6, y mostré como se pueden implementar colecciones de objetos que generen eventos. En esta parte trataré el cómo se pueden lanzar eventos desde un formulario u objeto que fue cargado desde la interfaz Form u Object. Eventos desde un Objeto FormUna de las grandes bondades de un objeto Form, es que podemos abrir cualquier formulario apuntando su referencia a un objeto Form, es así como podemos lanzar un formulario a partir de una cadena de texto. Esto es supremamente útil para reutilizar código de formularios desde clases. Esta técnica la he usado en muchas aplicaciones, y créame que es muy practico lanzar un formulario de datos en una línea de código, y dejar que una clase configure todo automáticamente. Voy a exponer un ejemplo sencillo, para vislumbrar la técnica. En primera instancia voy a presentar la solución en
donde los detalles de Digamos que tenemos una clase que se llama CFormDataAccess, la cual se emplea para envolver formularios genéricos de datos dentro de un componente. Esta clase abre el formulario desde su nombre, sin crear la clase explicita del formulario en sí (para esto se requiere de un objeto Form y de Forms.Add(FormName)). Luego configura el formulario según los parámetros pasados. Para seguir el ejemplo cree una DLL ActiveX, agregue la clase CEventsHandler (el código se encuentra en la primera parte de este articulo). El código de la clase CFormDataAccess es el siguiente: '//============================================================== '// NAME :
CFormsDataAccess '// AUTHOR : Harvey Triana
(harvey@geocoweb.net) '// DESCRIPTION :
Corte de código para ilustrar el ejemplo del '// articulo "Un Manejador de
Eventos Para Visual '// Basic Escrito en Visual Basic
- Parte 2 '// CEventsHandler es oculto al
cliente '//============================================================== Option Explicit Public Event Apply() Private WithEvents DataForm As Form '//EH Implementación Private WithEvents EventsHandler As CEventsHandler Public Function OpenForm( _ FormName As String, _ ParamArray Params() As
Variant) '// crea la instancia del formulario Set DataForm = Forms.Add(FormName) '// Detalles de carga en el formulario '// ... '// configura el formulario según
parámetros en Param()... '// ... '//EH
Implementación On
Error Resume Next Set
DataForm.EventsHandler = EventsHandler On Error GoTo 0 '//muestra el dialogo DataForm.Show vbModal Unload DataForm End Function Private Sub Class_Initialize() '//EH
Implementación Set
EventsHandler = New CEventsHandler End Sub Private Sub Class_Terminate() '//EH
Implementación Set EventsHandler
= Nothing End Sub '//EH Implementación Private Sub EventsHandler_RaiseEvents( _ Sender As
Object, _ EventName
As String, _ EventArgs
As Variant) Select
Case EventName Case
"Apply"
RaiseEvent Apply End Select End Sub '//============================================================== Las líneas de código que gestionan CEvensHandler aparecen en color violeta, y precedidas por el comentario EH Implementación. Como el código anterior oculta los detalles al cliente del manejador de eventos, se escribió un evento explicito de nombre Apply (para ilustrar la técnica). El problema que se debía resolver era el siguiente: “Como lanzar el evento Apply (o cualquier otro) al cliente, si el formulario se cargo desde un objeto Form. Pues bien, la clase CEventsHandler ha resuelve esto. Para completar el ejemplo, agregue a
'//============================================================== '// NAME : frmDialog1 '// AUTHOR : Harvey Triana
(harvey@geocoweb.net) '// DESCRIPTION :
Corte de código para ilustrar el ejemplo del '// articulo "Un Manejador de
Eventos Para Visual '// Basic Escrito en Visual Basic
- Parte 2 '// CEventsHandler es oculto al
cliente '//============================================================== Option Explicit '//EH
Implementación Private m_EventsHandler As CEventsHandler '//EH Implementación Public Property Set EventsHandler(v As
CEventsHandler) Set
m_EventsHandler = v End Property Private Sub cmdApply_Click() '//EH
Implementación
m_EventsHandler.Trigger Me, "Apply", Empty End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) If UnloadMode =
vbFormControlMenu Then Cancel = True Me.Hide End If End Sub Private Sub Form_Unload(Cancel As Integer) Set
m_EventsHandler = Nothing End Sub '//============================================================== El código luce algo extenso dados los detalles de EventsHandler, pero vale la pena, puesto que así como podemos lanzar un evento Apply, podemos lanzar muchos otros; en este caso tendrías que escribir código para dar los nombre explícitos en la clase CFormDataAccess, - este el precio de ocultar EventsHandler al cliente. Veamos el código del cliente (un EXE estándar y agregue el proyecto anterior en un grupo de proyectos): '//============================================================== '// NAME : Form1 '// AUTHOR : Harvey Triana
(harvey@geocoweb.net) '// DESCRIPTION :
Corte de código para ilustrar el ejemplo del '// articulo "Un Manejador de
Eventos Para Visual '// Basic Escrito en Visual Basic
- Parte 2 '//============================================================== Option Explicit Private WithEvents di As CFormDataAccess '//muestra del
formulario "frmDialog1" encapsulado en el '//componente, es
decir alguna DLL u OCX Private Sub Command1_Click() Set di = New CFormDataAccess di.OpenForm
"frmDialog1", "TEST0001", 1, True, "etc." Set di = Nothing End Sub Private Sub di_Apply() MsgBox "Fue lanzado el evento Apply" End Sub '//============================================================== El formulario del cliente no sabe nada de CEventsHandler, luce limpio y simple. Sin embargo es más labor para el que escribe el componente. Ahora bien, como se enuncio inicialmente, podemos hacer publica la clase CEventsHandler, crear una referencia explicita en el cliente, pasarla a la clase CDataFormAccess, y esta a su vez la pasa al frmDialog1. Esta estrategia hace más versátil el código de Eventos, pero hace estricto el código para el cliente. Bien, podemos mitigar esto al agregar un Constructor a CDataFormAccess, con EventsHandler como parámetro. Nota. VB6 no acepta constructores, pero es simple lograrlo si se sigue la regla de crear un método publico Constructor, y como regla (contrato) siempre llamarlo después de crear el objeto. Los tres módulos bajo esta estrategia lucen así: Componente: '//============================================================== '// NAME :
CFormsDataAccess '// AUTHOR : Harvey Triana
(harvey@geocoweb.net) '// DESCRIPTION :
Corte de código para ilustrar el ejemplo del '// articulo "Un Manejador de
Eventos Para Visual '// Basic Escrito en Visual Basic
- Parte 2 '// La clase EventsHandler es
publica '//============================================================== Option Explicit Private DataForm As Form '//EH Implementación Private m_EventsHandler As CEventsHandler Public Sub Constructor(pEventsHandler As
CEventsHandler) Set m_EventsHandler
= pEventsHandler End Sub Public Function OpenForm( _ FormName As String, _ ParamArray Params() As Variant) '// crea la instancia del formulario Set DataForm = Forms.Add(FormName) '// Detalles de carga en el formulario '// ... '// configura el formulario según
parámetros en Param()... '// lo que sea, no importa '... '//EH
Implementación On
Error Resume Next Set
DataForm.EventsHandler = m_EventsHandler On Error GoTo 0 '//muestra el dialogo DataForm.Show vbModal Unload DataForm End Function Private Sub Class_Terminate() '//EH
Implementación Set
m_EventsHandler = Nothing End Sub '//============================================================== Formuladio envuelto en el componente: '//============================================================== '// NAME : frmDialog1 '// AUTHOR : Harvey Triana
(harvey@geocoweb.net) '// DESCRIPTION :
Corte de código para ilustrar el ejemplo del '// articulo "Un Manejador de Eventos
Para Visual '// Basic Escrito en Visual Basic
- Parte 2 '// La clase EventsHandler es
publica '//============================================================== Option Explicit '//EH
Implementación Private m_EventsHandler As CEventsHandler '//EH Implementación Public Property Set EventsHandler(v As
CEventsHandler) Set
m_EventsHandler = v End Property Private Sub cmdApply_Click() '//EH
Implementación
m_EventsHandler.Trigger Nothing, "Apply", Empty End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) If UnloadMode =
vbFormControlMenu Then Cancel = True Me.Hide End If End Sub Private Sub Form_Unload(Cancel As Integer) '//EH Implementación Set
m_EventsHandler = Nothing End Sub Cliente: '//============================================================== '// NAME : Form1 '// AUTHOR : Harvey Triana
(harvey@geocoweb.net) '// DESCRIPTION :
Corte de código para ilustrar el ejemplo del '// articulo "Un Manejador de
Eventos Para Visual '// Basic Escrito en Visual Basic
- Parte 2 '// La clase EventsHandler es
publica '//============================================================== Option Explicit '//EH
Implementación Private WithEvents EventsHandler As CEventsHandler Private Sub Command1_Click() Dim di As CFormDataAccess Set di = New CFormDataAccess '//EH
Implementación Set
EventsHandler = New CEventsHandler '//EH Implementación di.Constructor EventsHandler di.OpenForm "frmDialog1",
"TEST0001", 1, True, "etc." '//nota. Los parametros que
"TEST0001", 1, True, "etc." '//son inventados yno tienen relevancia Set di = Nothing '//EH
Implementación Set
EventsHandler = Nothing End Sub '//EH Implementación Private Sub EventsHandler_RaisedEvent( _ Sender As
Object, _ EventName
As String, _ EventArgs As
Variant) Select
Case EventName Case
"Apply" MsgBox "Fue lanzado el evento
Apply" End Select End Sub '//============================================================== Si Usted es un programador versado en VB6, notara inmediatamente las ventajas de la segunda estrategia frente a la primetra. Primero, no tenemos que declarar en la seccion declaraciones el objeto de FormDataAccess. Segundo, no tenemos que delcarar eventos de FormDataAccess. Tercero, el numero de eventos y sus parametros son ilimitados (no afectamos la librería de tipos del componente). Cuarto, solo existe un WithEvents en todo el proyecto. Es importante anotar algo. Dado que el evento lo produce el Boton Apply del formulario envuelto en la clase, no debemos ejecutar el metodo Trigger pasando Me en Sender. Esto produciria peligrosas referencias circulares. Si dese pasar algo de la informacion del formulario, pasela en EvensArg, ya que al fin y alcabo es una Variant y acepta cualquier fuente de datos. Si desea pasar un Recordset al cliente, paselo como Clone y desconectado. ConclusionesLa clase EventsHandler impone un potente mecanismo para transferencia de eventos en VB6 y de la escritura de los mismos. La técnica luce avanzada para cualquier programador medio. El poder de VB6 esta en saber programar objetos y saberlos usar. |