Somos Expertos Access. Contacto atravez de Skype Skype logo expertos_7

Maximizando el reúso de código: Múltiples manejadores de eventos

Esta es la primera parte de maximizado el reusó de código. La segunda parte está aquí.

Una técnica de programación muy usada frecuentemente en aplicaciones de Access es la asignación de múltiples manejadores de eventos a un mismo evento de un objeto o compartir el mismo manejador de eventos en diferentes eventos de diferentes objetos. Para mostrarle un ejemplo, vamos a ver cómo mejorar un formulario continuo. Una característica muy buena de los formularios continuos  en el modo vista de datos es que tenemos un mejor control del diseño y de cómo podemos mostrar los datos. Una característica que tenemos en la vista de datos que no se encuentra en los formularios continuos es que podemos navegar fácilmente utilizando nuestro teclado.

Ahora tenemos un sin número de preguntas:

1)      ¿Cómo agregar el código necesario para que los formularios soporten  el uso de la tecla de navegación?

2)      ¿Cómo combinarlo con cualquier manejador de eventos existente?

3)      ¿Cómo hacerlo en la mínima cantidad de pasos?

La repuesta a las tres preguntas es mejor expresarla en un módulo de clases. Con la clase KeyNavigator, podemos agregar solo 4 líneas de código para cada formulario continuo (Sin contar las líneas en blanco ni la declaración de procedimiento) donde queramos habilitar la tecla de navegación.

Private kn As KeyNavigator

¿Cómo estas cuatro líneas proveen todas las funcionalidades? ¿No Necesitamos adjuntar otros manejadores de evento? ¿Cómo esto sabe cuándo se presiona una tecla y se mueve a otro registro? Al final del artículo voy a publicar el código completo pero por ahora miremos el procedimiento Init así como también la variable para la clase KeyNavigator para ver como conectamos los eventos en el módulo de clase.

Observe como tenemos una variable declarada a nivel de clase, con la palabra clave “WithEvents” la cual le permite saber a VBA que nosotros queremos suscribir los eventos de este objeto. Claro que luego tendremos que asignar el Init al WithEvents interno de la variable frm. Pero esto no es suficiente para suscribirse a los eventos del formulario.

Recuerde como usted diseña los manejadores de eventos usualmente, usted tiene que ir al tab de eventos de un objeto, agregar el “[Event Procedure]” o el procedimiento del evento para el evento donde usted quiere que se dispare e inmediatamente se genera un código en el módulo del formulario. El proceso sigue siendo el mismo pero los pasos son diferentes para el módulo de clase con un tab WithEvents. Asignamos el  “Event Procedure” a una de las propiedades del formulario como OnKeyDown la cual actualmente responde a la  “On Key Down” propiedad que se muestra en el tab de eventos del formulario. (De hecho, hay muchas propiedades que comienza con “On”  que son en realidad propiedades de evento, pero tenga en cuenta que algunas no tienen prefijo “On”; “AfterUpdate” y “BeforeUpdate” es un ejemplo notable de esto). Haciendo esto le estamos diciendo que queremos que el evento sea manejado. En otras palabras si no se le agrega esto el formulario pensará que no tiene nada que hacer y no hará nada y no se molestará en decirle a alguien “Hey, tengo un evento aquí, ¿Quiere hacer algo con él?”.

La asignación manual en el código es necesaria cuando se le pasa una clase a un formulario que no tiene ningún manejador de eventos. Esto funciona siempre y cuando el formulario seleccionado tenga o no un manejador de eventos para el mismo evento. El único problema es si usamos una función en lugar de un manejador de evento, la función se puede bloquear. Por ejemplo,  si le ponemos “=MyFunction” en la propiedad del evento, el código de arriba cambiaría su comportamiento y la función no se volvería a llamar.

En nuestro proyecto no nos gusta usar funciones preferimos usar manejadores de eventos en todos lados, que eso no es algo por lo cual preocuparse pero cuando hay diferentes proyectos es algo como para tomar en cuenta. Esto también se puede manejar de otra manera, detectando cuando una función existe y llamándola con Eval pero ese es un tema que se merece un artículo para poder explicarlo.

Ahora, con el objeto asignado  a una variable WithEvents y con el manejador de eventos establecido  a un [Event Procedure] podremos agregar un manejador de eventos. Como nombramos la variable “frm” podremos usarla como prefijo en vez de “Form_KeyDown” usaremos esto “frm_KeyDown”, pero ahí se está manejando el mismo evento para el mismo objeto.

Private Sub frm_KeyDown(KeyCode As Integer, Shift As Integer)

SI coloca su cursor en el procedimiento frm_KeyDown observe que el editor VBA muestra el “frm” en  la lista desplegable de la derecha y “KeyDown” en la de la izquierda. Si usted abre la lista desplegable de la izquierda, verá la misma lista de eventos de un formulario y seleccionando  uno de ellos le generará el código de un evento vacío,  igual como cuando usted agrega un nuevo evento de un procedimiento y cliquea  el botón “…”  en la vista de diseño.

Espero que ahora esté viendo como 4 líneas en el módulo del formulario original se pueden usar para agregar más detalles y mantener el código limpio. Si usted encuentra un error en el módulo de KeyNavigator arréglelo y todos los formularios que estén usando esta clase se actualizarán. ¿Con las nuevas funcionalidades también? Del mismo modo; vaya al módulo de KeyNavigator, agréguela, y todos los formularios disfrutaran de la nueva funcionalidad.

Lo más importante del código para manejar la tecla de navegación se debe mantener separado del código que especifica el formulario; no tenemos que preocuparnos de mezclar dos funcionalidades diferentes en el mismo manejador de eventos. Así que el formulario también puede usar el evento de KeyDown para otro propósito, usted todavía puede ejecutar el código específico del formulario en el procedimiento del Form_KeyDown y en ambos Form_KeyDown en el módulo del formulario y en frm_keyDown en el módulo de KeyNavigator van a responder al mismo evento.

Ya sabiendo esto hay algunos cabos sueltos que hay que ajustar.

1)      No se sabe el orden en que se va a disparar cada evento.

Hasta donde tengo entendido, no hay un documento explícito con el tema e información, con pruebas del orden en el que cada manejador de eventos se dispara, usualmente es el mismo orden en que se agregan a un objeto. Porque el módulo del formulario va a cargar primero, esto significa que el manejador de eventos del módulo de un formulario va a ser manejado antes que cualquier otro evento de cualquier otra clase. De todos modos, recomiendo antes de caer en cualquier suposición que un manejador de eventos se va a disparar antes que otro. Sería mejor si  hubiera una posibilidad de escribir el manejador  de eventos en una forma que no importe el orden. Piense en el manejador de eventos como en una isla con un solo puente de ida y vuelta hacia la isla principal (El objeto dispara lo eventos al mismo tiempo) pero no hay puentes para mandar dos objetos al mismo tiempo así que pasa uno primero y el otro después.

2)      No trate de modificar los parámetros de un evento dentro de un manejador de eventos.

Este no es el motivo #1 pero sí es muy importante. Usaremos el evento BeforeUpdate como ejemplo porque este tiene el parámetro Cancel:

Private Sub Form_BeforeUpdate(Cancel As Integer)

Cuando establecemos  el Cancel = true, el evento BeforeUpdate se cancelará. Pero esto no significa que el manejador de eventos cancelará el evento y  le dirá a los otros manejares de eventos que se detengan. De todos modos para asegurase que los otros manejadores de eventos también sean cancelados utilice  un if :

Private Sub frm_BeforeUpdate(Cancel As Integer)

Es bastante razonable leer el parámetro para ver si un manejador de eventos ha cancelado el evento, pero no es una buena idea hacer algo parecido a esto:

Esto puede ser confuso y como expliqué no estamos realmente seguros de en qué orden se disparan lo manejadores de eventos. En otras palabras, esto puede dar un resultado inesperado y terminar   cancelando algo que no debería cancelarse. Sé que el ejemplo es un poco absurdo pero es solo para mostrarle porque no debemos diseñar nuestros manejadores de eventos con otros parámetros, simplemente acepte lo que tiene por defecto y cámbielo solo si es necesario.

1)      Evite el comando Docmd si es posible, cuando  escribe código non-interactivo

Cuando escribe código que funciona con otras variables de un objeto, no siempre  tenemos todo el conocimiento acerca del contexto de un formulario. Si usted mira el código de ejemplo completo se dará cuenta que no hay ninguna referencia  a DoCmd en ningún lado y por una buena razón. Los métodos de DoCmd son heredados interactivamente, ellos imitan las acciones que pasan cuando un usuario hace click y esto funciona con el objeto activo pero no tenemos una garantía de que el objeto es el mismo que queremos. Hagamos un DoCmd.RunCommand acCmdRecordGoToNew por ejemplo. No hay parámetro que nos especifique que acción debe realizar el formulario. DoCmd.GoToRecord nos das un parámetro para entrar el nombre del formulario pero esto no funcionará si el formulario es un sub-formulario; tiene que ser un formulario principal. Cuando se escribe código robusto usualmente es necesario identificar y usar métodos que no sean interactivos. Algunas veces cuando esto no se puede evitar. Por ejemplo, DoCmd.OpenForm / DoCmd.Close Esta es la única manera de  agregar / eliminar un formulario de la colección de formularios.

Esté pendiente para la segunda parte donde mostraremos como agregar esas 4  líneas de código para 100 formularios continuos.

Aquí le dejo el código completo para la clase keyNavigator:

Option Compare Database

Publicado en Access Help

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

 

Quienes Somos

ExpertosMicrosoftAccess.com es un servicio de la empresa IT Impact, Inc., una compañía de programación y servicios para empresas en Latino América. Ofrecemos servicios en .Net, SQL Server y Microsoft Access. Muchos de nuestros desarrolladores han obtenido el galardón de Access MVP, un título proveído por Microsoft a aquellos que han hecho aportes a la comunidad y que han demostrado tener conocimientos superiores del producto.

Nuestro Equipo

  • Le ayudamos a "Descubrir el poder de sus datos™" con reportes y sistemas de Access excepcionales .
  • Creamos soluciones de bases de datos personalizadas utilizando Microsoft Access y / o SQL Server.
  • Nuestros consultores ganaron sus estrellas en las empresas de servicios y/o manufactura antes de convertirse en programadores.

Blogs anteriores