Truco para Cerrar formulario Nivel Superior en Load o Init

2,418 views
Skip to first unread message

Antonio Meza

unread,
Jul 6, 2015, 3:53:24 PM7/6/15
to publice...@googlegroups.com
Hola!!!

Hace tiempo que había querido poder cerrar un formulario de nivel superior incluso normal desde el LOAD o INIT pero siempre se quedaba colgado el proceso en windows, es decir no se liberaba el ejecutable incluso en modo desarrollo se queda el proceso activo y tenia que ir al Menú Program y Cancel para detenerlo.

El problema no esta en el formulario como tal, ya que este ejecuta bien su función, el problema realmente esta en el READ EVENTS que no se libera porque no se entera de que fue lo que paso en el formulario al cerrarlo desde el Load o Init.

Por ejemplo el siguiente código en un archivo PRG

* Iniciar SET, rutas, etc etc
* Ejecutar formulario
     
Do formulario_principal.scx
     
Read Event

Al ejecutar esto, en el formulario se inician los eventos (son muchos) pero los que interesan, el LOAD y después el INIT y entonces salta el READ EVENTS, el formulario queda en pantalla y al presionar un botón salir o cerrar desde la X, se ejecuta el Destroy del formulario que debe tener un CLEAR EVENTS y entonces el READ EVENTS se finaliza.

En los foros, ayuda y paginas web dicen que pasa terminar un formulario desde el LOAD solo hay que poner un RETURN .F: y realmente si lo hace incluso lo mas correcto es poner así

Load del formulario
this.Destroy   && Para que se ejecute el Clear Events o algo que se requiera
return .f.

El mismo caso sera para el evento INIT, que a diferencia de LOAD para que el INIT se libere es necesario poner primero This.Release o this.Destroy y luego el Return .f. para que el formulario salga correctamente

Init del formulario
* Uaar Release o Destroy
* this.Release  
this.Destroy   && Este es el mas recomendado
return .f.

Destroy del formulario
Clear Events

Pues bien ya hemos cerrado el formulario desde el Load o Init y se ejecuto el Clear Evens, pero de todas formas la siguiente linea que es se va a ejecutar es el Read Events y se quedara bloqueada la aplicación porque el Clear Events no sirve de nada porque aun no hay un READ EVENTS activo, es decir el formulario ejecuto el Clear Events y regreso el control al PRG que ejecutara por primera vez el Read Events.

El TRUCO, es saber que fue lo que paso dentro del formulario para entonces decidir si se ejecuta el READ EVENTS o no, así de sencillito, el código del PRG seria el siguiente

* PRG Inicial
* Iniciar SET, rutas, etc etc

* Variable para saber que paso dentro del formulario.
     
Private _errorLoad_Init as Boolean
     _errorLoad_Init
= .f.
* Ejecutar formulario
     
Do formulario_principal.scx
* Decidir que hacer
     
if _errorLoad_Init
         
* Hubo un error, no ejecutar read events
     ELSE
         Read Events
     ENDIF
*Liberar objetos
clear all
close all
* etc etc

Código dentro del LOAD del formulario

* Cargar librerías
 
if this.librerias()  && Ejemplo
     
* Bla bla bla
 
else
     MESSAGEBOX
("Error en el Load, no se cargaron las librerías")
     _errorLoad_Init
= .t.
  endif
* Verificar si hubo un error
   IF _errorLoad_Init
     
this.Destroy
      RETURN
.f.
   ENDIF

Y con esto el programa ya no se quedara colgado y podemos cerrarlo sin problema desde el Load o Init.

NOTA: Si ejecutan un formulario dentro de otro formulario ya no es necesario usar el truco puesto que el segundo formulario no requiere de un Clear Events ni un Read Events, por lo que solo es para un formulario principal,
Para que serviría hacer algo así? bueno a veces necesitamos código que se ejecuta dentro del LOAD y si algo importante no se ejecuto es mejor notificar el problema y cerrar el formulario que dejarlo abierto y siga tronando como palomita de maíz!!

Espero que les sirva y haya quedado claro el problema y una posible solución.

Si alguien sabe de una mejor opción (probada no supuesta)  sera bien recibida.

saludos
Antonio Meza

Luis Maria Guayan

unread,
Jul 6, 2015, 6:00:12 PM7/6/15
to publice...@googlegroups.com
Una aclaración: Los formularios no se cierran en el LOAD, si el método Load retorna .F. el formulario no llega a cargarse, por lo cual tampoco se ejecuta el método Destroy

Para controlar una salida de un ciclo READ EVENTS en el Load del formulario:

IF NOT Condicion_de_carga_del_formulario
    CLEAR EVENTS
    RETURN .F.
ENDIF

Luis María Guayán
Tucumán, Argentina
_______________________________
Comunidad Visual FoxPro en Español
http://comunidadvfp.blogspot.com

Antonio Meza

unread,
Jul 6, 2015, 6:21:02 PM7/6/15
to publice...@googlegroups.com, luism...@gmail.com
Maestro LuisMa!!

Es correcto lo que comenta al poner el Return .f. en el Load no se ejecuta el Destroy, por ello es recomendable llamarlo antes como lo comente y como recomiendan por ejemplo aquí fue donde vi, También es correcto que no se destruye como tal porque no se creo!!


El código que puso de ejemplo funciona si ya hay un Read Events activo, el problema que yo expuse es cuando no lo hay, entonces el código no funcionaria, porque en Read Events no existe aun y por lo tanto el Clear Events no hará nada.

Es decir su ejemplo funciona perfectamente si tiene algo así en un PRG

Do menu.mpr
Read Events

Y luego desde el menú llama un formulario que en el LOAD tiene el código

IF NOT Condicion_de_carga_del_formulario
    CLEAR EVENTS
    RETURN
.F.
ENDIF

Incluso lo sacaría del programa debería ser así (solo son ejemplos)

IF NOT Condicion_de_carga_del_formulario
    RETURN
.F.
ENDIF

Pero si tiene un PRG así

Do formulario.scx
Read Events

Es donde el Clear Events no hará nada porque aun no se ejecuta el Read Events, no se si me explico? primero se ejecuta el formulario y todos los eventos y luego regresa el control al PRG que es la linea del Read Events, pero este Read Events no se entera de lo que se haya hecho en el formulario si en el Load se puso Return .f. si se aplico un Clear Events, si en el init un return .f. etc.

saludos
Antonio Meza

Victor Espina

unread,
Jul 7, 2015, 8:06:29 AM7/7/15
to publice...@googlegroups.com, solv...@gmail.com
Usar una variable privada y modificarla en el Init o Load del formulario definitivamente funciona, pero no respeta el principio de encapsulamiento al hacer que tu formulario principal dependa de una variable extarna.  Una alternativa seria:

LOCAL oMainForm
DO mainForm NAME oMainForm NOSHOW
IF VARTYPE
(oMainForm)="O"
 
* Formulario fue cargado correctamente
 oMainForm
.Show()
 READ EVENTS
ENDIF


* Codigo de salida normal



Victor Espina

Antonio Meza

unread,
Jul 7, 2015, 1:08:00 PM7/7/15
to publice...@googlegroups.com, vesp...@gmail.com, solv...@gmail.com
Excelente Maestro Victor voy a ajustar el código!!

Muchas gracias!!

Saludos
Antonio Meza
Reply all
Reply to author
Forward
0 new messages