6 de febrero de 2015

¿Cuándo ocurren los eventos?


Texto original: When Does It Happen?
http://www.jamesbooth.com/eventorder.htm
Autor: Jim Booth
Traducido por: Ana María Bisbé York

En el desarrollo de aplicaciones en Visual FoxPro somos siempre dependientes de la ocurrencia de los eventos. Cada vez que tecleamos o damos clic del ratón es muy importante para el correcto funcionamiento de la aplicación. En realidad ¿cuánto conoce acerca de cuándo ocurren las cosas en VFP? Este mes vamos a examinar algunos de los eventos importantes y encontrar realmente en qué momento ocurren.

Eventos y métodos.

Primero, antes de meternos en los eventos que se ejecutan durante varias operaciones en Visual FoxPro, permítanme clasificar los eventos y métodos que se encuentran disponibles en el producto. Prefiero referirme a estas localizaciones de código como métodos de evento y métodos. La diferencia entre un método de evento y un simple método está en cómo se activa. Un método simple solo se dispara si una línea de código lo ha llamado, puede tener un comportamiento predeterminado dentro de VFP o puede simplemente estar donde se pueda escribir el código y luego llamar a ese código cuando desee.

Un método de evento es automáticamente llamado si un evento ocurre, por ejemplo el método de evento KeyPress de un control será automáticamente llamado en cualquier momento que el usuario presione una tecla mientras el foco lo tenga este control. Es importante diferenciar entre el evento (presionar la tecla) y el método de evento (KeyPress) que se activa como resultado del evento que ocurre. Llamar a un método de evento en un código, no causa que el evento asociado ocurra. Simplemente corre el código de ese método de evento.

Tomando y perdiendo el foco.

Existe un número de métodos de evento y métodos asociados con el recibir y/o perder foco del control. Los métodos de evento relacionados con el recibimiento o pérdida del foco son When (método de evento), GotFocus (método de evento), SetFocus (método), Valid (método de evento) y LostFocus (método de evento).

Para utilizar las ventajas del modelo de eventos en Visual FoxPro es necesario entender claramente los métodos de eventos que son activados y el punto en el que son activados. En el proceso de recibir el foco la secuencia de métodos de eventos es 1 – When y luego 2 – GotFocus

El método de evento when puede ser pensado como el lugar para determinar si se le permitirá o no al foco llegar al control. Devolviendo un valor .F. desde el método de evento When evita que el foco llegue al control. Una vez que el evento devuelve un valor .T. el GotFocus es disparado (si el When devuelve .F. no se ejecuta el GotFocus.) El GotFocus puede ser clasificado como un método de evento en el cual se prepara al control para recibir el foco, ya que solo se dispara si el control en efecto recibirá el foco.

El método SetFocus tiene un comportamiento predeterminado en el inicio del proceso de recibir el foco por el control. El método SetFocus de un control es similar a la variable de foxpro2.x _curobj Existen dos controles que actúan ligeramente diferente con relación al método de evento When. Son el ListBox y Combobox. Con estos dos controles, el evento When se dispara de igual forma que para otros controles, cuando llega el foco y antes de que el objeto en realidad lo tome. El When puede devolver .F. y evita que el foco llegue al control.

Sin embargo, con listas y combos, el When también se dispara a cada momento cuando el item seleccionado cambia. Debido a este comportamiento es importante ser cuidadosos con el código que se coloca en el evento When de listas y combos. Debe estar seguro que el When se disparará tantas veces para estos controles, como el usuario navegue por sus listas.

El proceso de pérdida del foco es similar. Existen dos métodos de evento involucrados, Valid y LostFocus. El Valid se dispara primero y puede ser utilizado para evitar que el control pierda el foco. Devolver .F. en el Valid ocasionará que el control retendrá el foco. Devolver .T. del valid permitirá al foco abandonar el control y con seguridad se disparará el LostFocus. Igual que el When y GotFocus, el Valid puede ser usado para decidir si se permitirá al foco abandonar el control y el LostFocus puede ser utilizado para controlar las reacciones del control cuando pierda el foco.

Actualizando los datos.

Visual FoxPro es una herramienta de administración de Datos y como tal tiene mucho poder y es muy fácil de manipular las capacidades de amarre. Muchos de los controles de VFP son capaces de ser atados a fuentes de datos fijando sus valores en la propiedad ControlSource. El uso de la propiedad ControlSource provoca que el control automáticamente actualice el origen de datos (ControlSource) cuando el valor del control es cambiado.


Aunque, cualquier cosa en la vida, la actualización del ControlSource toma lugar en un punto de tiempo específico. Conocer exactamente cuando ocurre la actualización es crítico para obtener la mayor flexibilidad de los controles de VFP.

Existe un grupo de situaciones relacionadas con la actualización del ControlSource, a lo que algunos llaman “bugs”. Uno de estos casos fue cuando un desarrollador que llamaba al thisform.refresh() en el evento InteractiveChange de un cuadro de texto y se quejaba porque el cuadro de texto mantenía el mismo valor del ControlSource. Otros han encontrado que usando el GetFldState(-1) desde el botón de la barra de herramientas no refleja los cambios del control que tiene el foco, cuando el botón de la barra de herramientas es pinchado. Ninguno de estos son bugs, ambos ocurren “por diseño”. ¿Qué?!!
Si, el diseño de los controles en VFP es tal que ellos actualizan su ControlSource con su Value inmediatamente antes de que sea llamado el evento Valid. Si el evento Valid no es llamado entonces el ControlSource no será actualizado.

En la sección previa hemos discutido el evento Valid y encontramos que se activa en respuesta a la intención del control de perder el foco.
En el primer caso, el InteractiveChange, el control no pierde el foco, no se dispara el Valid y el ControlSource retiene su valor original, la llamada a refrescar (Refresh) del formulario causa que el control también sea refrescado, durante su refresque re_ lee su ControlSource (el que todavía tiene su control original)

En el segundo caso, la barra de herramientas, el problema se encuentra en el hecho de que las barras de herramientas y menús nunca reciben el foco. Como el toolbar nunca recibe el foco el control nunca pierde el foco y el Valid nunca será disparado y el ControlSource no será actualizado.
Antes de mirar las soluciones, vamos a correr un pequeño test para ver los efectos de este comportamiento. En esta prueba cree un formulario con un cuadro de texto (textbox) que tenga un campo de una tabla como ControlSource. Luego vaya a cada uno de los siguientes eventos y entre:

DEBUGOUT “<Event Name> ControlSource: “ + EVALUATE(THIS.ControlSource) ; 
   + “Value: “ + THIS.Value 

Reemplace <Event Name> con el nombre del método de evento en particular en el que está colocando el código. Coloque este código en los métodos de evento: GotFocus, InteractiveChange, KeyPress, Valid, y LostFocus

Luego, abra el depurador y corra el formulario. Teclee el nuevo valor dentro del textbox y luego presione Tab para salir del textbox. En la ventana del Depurador verá unos resultados similares a la tabla que se muestra a continuación

Método de EventoControlSourceValue Comentarios
GotFocusJonesJonesEl ControlSource y Value son iguales en el textbox que tiene el control
InteractiveChangeJonesSCuando escribe una letra, el primer método de evento que se activa es el InteractiveChange. Durante el InteractiveChange la propiedad Value fue alterada pero el ControlSource retiene su valor original.
KeyPressJonesSDespués del InteractiveChange, el método de evento KeyPress es llamado. El ControlSource se mantiene inalterado con relación al Value
InteractiveChangeJonesSmEste proceso continúa mientras continúe escribiendo en el control textbox.
KeyPressJonesSm
InteractiveChangeJonesSmi
KeyPressJonesSmi
InteractiveChangeJonesSmit
KeyPressJonesSmit
InteractiveChangeJonesSmith
KeyPressJonesSmith
KeyPressJonesSmithEsto es cuando se presiona el Tabulador (KeyPress) que se usa para salir del control
ValidSmithSmithAhora, el método de evento Valid es activado, el ControlSource es actualizado con el nuevo valor
LostFocusSmithSmithComo el LostFocus se activa después del Valid, el ControlSource ya tiene el nuevo valor.

Observe que en la tabla hay un período de tiempo en el que el valor del ControlSource no es igual al Value del Control. Si se hubiera refrescado el control en ese tiempo el valor del control (Value) hubiera sido revertido con el valor actual del origen de datos (ControlSource).

Si no presiona el tabulador después de introducir el dato y hace clic en la barra de herramientas o selecciona una opción del menú. El textbox va a retener aun el foco. Esto significa que el valid no se ha disparado y el ControlSource no será actualizado. El código ejecutado por el botón del toolbar (o menú de opción) utilizado GetFldState(-1) para chequear los campos modificados, no verá que el campo actual ha sido modificado. Esto es debido a que el campo no ha cambiado aún.

La solución es forzar el control actual a actualizar el ControlSource en cualquier código de la barra de herramientas u opción de menú que utilice GetFldState() o TableUpdate(). Esto lo puede hacer simplemente llamando el SetFocus de ese control. Llamando al SetFocus del control provoca que el VFP ejecute primero el Valid y LostFocus antes de ejecutar el método SetFocus. Así el control va a actualizar su ControlSource.

Debe tener mucha precaución obrando de esta manera. Existe siempre la posibilidad de que el formulario actual no tenga control activo o que el control activo no tenga método SetFocus. Este código de ejemplo muestra cómo puede verificar estas situaciones.

IF TYPE(“_screen.ActiveForm.ActiveControl.Name”) = “C”
     IF PEMSTATUS(_screen.ActiveForm.ActiveControl,”SetFocus”,5)
          _screen.ActiveForm.ActiveControl.SetFocus()
     ENDIF
ENDIF
* El resto de su código va aquí.

El código de arriba verifica el tipo de la propiedad Name del control activo en el formulario activo. Si la propiedad Name es de caracteres entonces podemos asumir con seguridad que el control activo es un objeto. El segundo IF verifica si el ActiveControl tiene un método SetFocus. Si lo tiene, lo llama. Llamar al SetFocus provoca el proceso de pérdida del foco llamando los métodos de evento Valid y LostFocus y actualizando el ControlSource.

¿Por qué es esto tan poco intuitivo? ¿Por qué no trabaja esto de la forma en que yo pienso que trabaja? ¿Por qué es tan raro? Bueno, su rareza es algo relativo, para alguna gente este comportamiento pudiera ser raro, para otros es visto como la mejor manera de hacer que las cosas funcionen. Para una persona es comida, lo que para otra es veneno.

Lo importante en este artículo es la prueba que se ha realizado. Los resultados son solo descriptivos del modelo de evento para un conjunto particular de procesos en VFP. Ser capaz de crear una lista de eventos y el estado de las cosas durante estos eventos es la utilidad real de este artículo.

Puede tratar de memorizar cada matiz de Visual FoxPro si desea. No creo que nunca llegue a conocerlos a todos y tampoco creo que sea un buen uso del tiempo memorizar las peculiaridades de cada herramienta. Lo que si es un buen uso del tiempo es dejar un proyecto de desarrollo de la aplicación por unos minutos y construir una pequeña prueba para el estudio de que es lo que pasa en una situación determinada. Después regresar al proyecto y programar en correspondencia con lo que ha aprendido durante la prueba

4 comentarios :

  1. Muy buen artículo. Claro, conciso y muy interesante.
    Gracias LMG por compartirnos temas de calidad.

    ResponderEliminar
  2. Como siempre, un interesante artículo. Muchas gracias por estas valiosas cápsulas de conocimiento.

    ResponderEliminar
  3. Excelente artículo... yo programé en dBase y Foxpro para DOS, y los eventos para los objetos eran pocos, con estas herramientas se tiene mas control del formulario

    ResponderEliminar
  4. Excelente articulo, yo programé en dBase y FoxPro para DOS, se tenian tenian pocos eventos sobre los objetos y ventanas, solo eran el when y valid, ahora se tiene mas control del formulario

    ResponderEliminar