Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Como abortar correctamente un proceso que es interrumpido por el cierre del Form (https://www.clubdelphi.com/foros/showthread.php?t=47431)

gluglu 28-08-2007 11:08:31

Como abortar correctamente un proceso que es interrumpido por el cierre del Form
 
Hola amig@s !

En el OnActivate de un Form llamo a un proceso que tarda algunos segundos en generar la pantalla que quiero mostrar.

Código Delphi [-]
procedure TForm.FormActivate(Sender: TObject);
begin
  Self.OnActivate := nil;
  FormRepaint;
end;

Si el usuario, durante dicho proceso FormRepaint, hace click para cerrar el Form, de manera inmediata se llama a la rutina FormClose.

Código Delphi [-]
procedure TFormMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
  FormMain := nil;
end;

pero me he dado cuenta que al finalizar FormClose, prosigue con FormRepaint en el punto en el cual se interrumpió por el cierre del Form.

Y finalmente, entre otras cosas, FormMain no queda a Nil.

Como puedo entonces abortar correctamente FormRepaint dentro del proceso FormClose ?? O como se solucionaría esta problemática de la manera correcta ?

He intentado meter toda el código de FormRepaint en un Try Except pero a pesar de ello no me produce ninguna excepción y por lo tanto no sale del bucle Try, prosiguiendo como indica antes en el mismo punto en donde se interrumpió por la llamada a FormClose.

Gracias por vuestra ayuda.

duilioisola 28-08-2007 13:34:29

Te respondo como lo haría yo. Esto no aborta el FormRepaint, pero por lo menos no te generará los errores de no liberar al form.

Variable global al form:
PuedoCerrar : boolean;

Código:

procedure TForm.FormActivate(Sender: TObject);
begin
  Self.OnActivate := nil;
  PuedoCerrar := False;
  FormRepaint;
  PuedoCerrar := True;
end;

procedure TFormMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if (PuedoCerrar) then
  begin
    Action := caFree;
    FormMain := nil;
  end else
    Action := caNone;
end;


gluglu 28-08-2007 13:41:48

Gracias por responder.

No quiero que se impida el cierre del Form, que es lo que ocurriría con tu propuesta.

Lo que quiero es que se pueda cerrar el form abortando el proceso FormRepaint. :o

gluglu 28-08-2007 13:42:33

Por cierto, en estos casos, Bienvenido al Club ! ;)

seoane 28-08-2007 13:48:27

:confused: ¿Y que haces dentro de FormRepaint? Si es un proceso normal, el cierre no se debería de producir hasta que terminara el FormRepaint, así que supongo que estas utilizando Application.ProcessMessage ¿es así?

Explicate un poco mas :p

duilioisola 28-08-2007 14:09:03

Gracias por la bienvenida... he utilizado el foro para resolver muchos de mis problemas y pensé que sería bueno escribir algo para los demás.

Otra opción con 2 variables globales... en este caso, se llena QuieroCerrar, pero no se cierra y después del FormRepaint, si es True, se cierra.

Nuevamente, no aborta el FormRepaint, pero cerrará el form correctamente después de todo.

Espero que se parezca a lo que buscas.

(para acelerar el cierre, quizás puedas usar la variable global PuedoCerrar dentro del procedure FormRepaint para NO ejecutar ciertas cosas que tarden mucho.
ej. pseudocodigo
Código:

procedure FormRepaint
begin
  if PuedoCerrar then
      [primera cosa a realizar]
  if PuedoCerrar then
      [seguinda cosa a realizar]
  if PuedoCerrar then
      [tercera cosa a realizar]
  if PuedoCerrar then
      [primera cosa a realizar]
end

)

Variable global al form:
PuedoCerrar : boolean;
QuieroCerrar : boolean;

Código:

procedure TForm.FormActivate(Sender: TObject);
begin
  Self.OnActivate := nil;
  PuedoCerrar := False;
  QuieroCerrar := False;
  FormRepaint;
  PuedoCerrar := True;
  if (QuieroCerrar) then
      Close;
end;

procedure TFormMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if (PuedoCerrar) then
  begin
      Action := caFree;
      FormMain := nil;
  end else
  begin
      Action := caNone;
      QuieroCerrar := True;
  end;
end;


gluglu 28-08-2007 14:28:22

Había utilizado ya 'Flags' para abortar el proceso FormRepaint. Todo funciona en teoría correctamente, cancelo el repintado y cierro el form.

Pero preguntaba si había otra manera más 'correcta'. El inconveniente de utilizar ese 'Flag' para abortar el proceso de repintado, es que de hecho al final del todo, después de cerrar el Form, la variable FormMain no queda a Nil.

Por lo tanto, en mi menú principal de la aplicación, dicho Form aparece como si estuviera 'activo'.

seoane 28-08-2007 15:00:35

Cita:

Empezado por gluglu (Mensaje 226501)
Por lo tanto, en mi menú principal de la aplicación, dicho Form aparece como si estuviera 'activo'.

Como compruebas si el form esta activo, supongo que así:
Código Delphi [-]
  if FormMain <> nil then
   ... etc

Prueba con esto:
Código Delphi [-]
function Existe(F: TForm): Boolean;
var
  i: integer;
begin
  for i:= 0 to Screen.FormCount - 1 Do
    if Screen.Forms[i] = F then
    begin
      Result:= TRUE;
      Exit;
    end;
  Result:= FALSE;
end;

if Existe(FormMain) then
  etc ...

gluglu 28-08-2007 15:09:03

Pues si, Domingo. Sería otra forma de comprobarlo.

Yo lo tengo así :

Código Delphi [-]
procedure TMainform.FormLoQueSeaClick(Sender: TObject);
begin
  If not Assigned(FormLoQueSea) then begin
    Screen.Cursor := crHourGlass;
    FormLoQueSea := TFormLoQueSea.Create(Self);
    Screen.Cursor := crDefault;
  end;
  FormLoQueSea.Show;
  if FormLoQueSea.WindowState = wsMinimized then
    FormLoQueSea.WindowState := wsNormal;
end;

Especifico que se trata de una aplicación MDI. :rolleyes:

Casimiro Notevi 28-08-2007 15:09:22

No entiendo bien el motivo de cerrar cuando está abriendo, pero en fin... ¿por qué no lo pones invisible, hide, y luego lo pones a nil desde donde lo has llamado.
Código:

procedure TfrmBackRestAux.FormClose(Sender: TObject; var Action: TCloseAction);
begin 
  inherited;
  Action := caHide;
end;

Código:

  frmAux := TfrmBackRestAux.Create(owner);
  frmAux.ShowModal;
  // frmAux.Free;
  FreeAndNil(frmAux);

Creo que te puede servir algo así.

gluglu 28-08-2007 15:41:03

Al final os agradezco a todos vuestras respuestas, pero no creía que fuera para tanto revuelo.

Ya puesto doy la explicación completa.

Es un form que se crea y tarda cierto tiempo en buscar los datos y generar la presentación. (Ya viene de algunos hilos en este foro incluso anteriores). Al principio realizaba la primera 'generación' del Form en el OnCreate, y al mostrarlo la primera vez, ya estaba todo bien presentado.

Ya que ese form puede ser 'actualizado' cuando lo quiera el usuario o bien mediante un Timer que también tengo puesto, decidí 'acortar' el tiempo que tarda en presentarlo la primera vez, sacando la función de 'repintado' del OnCreate y pasarlo al OnActivate.

Así de esta manera, el Form aparece casi de inmediato (en vez de tardar aprox. 4-5 segundos en aparecer), y una vez que se muestra el form digamos 'en blanco' entonces en el OnActivate llamo al repintado y el usuario va viendo en pantalla como se va actualizando.

Con tantas pruebas que hace uno, pues resulta que en una de estas veces me apresuré en cerrar el Form antes de terminar el repintado. Y ví que daba un error, cosa que como siempre se debe evitar a toda costa ! :p

Entonces me puse a analizarlo y me dí cuenta de todo lo expuesto anteriormente.

Por qué cerrar el form antes de terminar de crearlo ?? Por lo anteriormente expuesto y porque los usuarios son muy dados a hacer Click en todos los sitios incluso antes de haber terminado algo. Y claro, ahí saltaba el error.

Y mi pregunta fue como hacerlo 'correctamente' y si había una forma 'bonita' para ello.

También pensé en la última opción que plantea Casimiro, que es hacer el FreeAndNil en el sitio donde se llama.

Lo dicho, no creía que este hilo fuera a acabar con esta extensión. En cualquier caso, una vez más, muchas gracias por todas vuestras propuestas.

Saludos a todos :D

Edito : Casimiro, no puedo hacer el FreeAndNil desde donde lo llamo porque es un formulario MDI que se muestra NO Modal. Y por eso también la comprobación que indicaba más arriba y que me contestó Domingo.


La franja horaria es GMT +2. Ahora son las 00:27:51.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi