Ver Mensaje Individual
  #9  
Antiguo 09-02-2010
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Reputación: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por rgstuamigo
he probado colocar un boton en el cual llamo al método Close del formualrio y no he tenido problemas
Porque has tenido suerte

Yo hice la prueba del compañero y también obtuve un Access Violation. Luego agregué un tercer formulario al proyecto y "funcionó". O sea que, dependiendo de según qué circunstancias, puedes o no tener un problema.

El punto es, que no puedes usar FreeAndNil en el evento OnClose (y en ningún evento del formulario) por la misma razón que no puedes usar Free y debes usar Release en su lugar.

Tú mismo has observado que Release hace un Post del mensaje CM_RELEASE que, a su vez, genera la llamada a Free. Pero, al hacerse vía un Post, se garantiza que el formulario que se destruye ya ha procesado todos los eventos.

Al usar FreeAndNil e invocar el método Close tal como hace el compañero, el problema está en que el formulario se destruye cuando el evento Button1Click aún no termina.

En todo caso, podría funcionar algo como:

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

De todas maneras, a mi en lo particular no me gusta este tipo de métodos. Se supone que una clase no debería hacer referencia a ninguna instancia en particular de ella.

Lo que yo hago en estos casos, es usar el mecanismo de notificaciones entre componentes dado por FreeNotification y Notification.

Cuando creo el formulario, uso

Código Delphi [-]
Application.CreateForm(TForm2, Form2);
Form2.FreeNotification(Self);

Esto asegura que Self (el formulario desde donde se abre el segundo formulario) sea notificado cuando Form2 se destruya:

Código Delphi [-]
destructor TComponent.Destroy;
begin
  Destroying;
  if FFreeNotifies <> nil then
  begin
    while Assigned(FFreeNotifies) and (FFreeNotifies.Count > 0) do
      TComponent(FFreeNotifies[FFreeNotifies.Count - 1]).Notification(Self, opRemove);
    FreeAndNil(FFreeNotifies);
  end;
  DestroyComponents;
  if FOwner <> nil then FOwner.RemoveComponent(Self);
  inherited Destroy;
end;

Entonces, la parte que faltaría, es redefinir el método Notification de TForm1 para, ahí sí, poner en nil la variable:

Código Delphi [-]
procedure TForm1.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;

  if (AComponent = Form2) and (Operation = opRemove) then
    Form2 := nil;
end;

// Saludos
Responder Con Cita