Ver Mensaje Individual
  #4  
Antiguo 10-09-2004
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
Un comentario:

Creo que manejar una lista propia de ventanas podría ser útil en determinados contextos pero en un caso general estamos repitiendo una lista que ya existe:

Screen.Forms

Y en el caso de aplicaciones MDI, el formulario principal tiene el arreglo MDIChildren que lista todas las ventanas hijas.

Por otra parte no veo cómo tener dicha lista de ventanas nos ayuda a liberar correctamente los formularios creados.

Para liberar el objeto formulario basta con poner

Action := caFree;

en su evento OnClose.

El único problema que puede presentarse aquí es cuando necesitamos poder abrir nuevamente el formulario ya que debemos poder determinar si está ya creado o no.

Con formularios MDIChildren esto normalmente no es asunto de preocupación ya cada vez que se abre un documento se utiliza otra ventana y no se reusa una anterior de manera que, en efecto, creamos uno nuevo.

Tampoco hay problema, como ya se vió, en el caso de ventanas modales ya que el formulario se libera inmediatamente después de cerrarse- y por cierto, también en este caso se puede hacer Action := caFree para no tener que llamar a Release (o Free, que me parece que Release sólo es necesario cuando se desea liberar el formulario desde un evento del mismo).

Queda el caso de formularios que nos son modales y de los cuales sólo queremos que haya una instancia.

La manera más común es es usar la variable que se declara automáticamente cuando se añade el formulario durante el diseño: se pone a nil en el evento OnClose para así poder verificar con certeza si existe o no al momento de intentar abrilo:


Código Delphi [-]
// Abrir formulario
if Form2 <> nil then
  Form2 := TForm2.Create(...);

Form2.Show;

Pero esto tiene el defecto de que se está haciendo referencia a un objeto global y no sólo eso, sino que la clase en sí del formulario hace referencia (en su evento OnClose) a una instancia particular; ambas prácticas no aconsejables.

Otra opción mejor es olvidarse de la variable global (de hecho casi siempre debería uno olvidarse de ellas) y usar una variable privada en el formulario principal y siguiendo la misma técnica del OnClose. Con esto se evita el uso de una variable global aunque persiste el hecho de que la clase hace referencia a una de sus instancias en particular.

El método que prefiero es el de la notificación:

Código Delphi [-]
type
  // Formulario principal
  TForm1 = class(TForm)
  private
    Form2: TForm;

  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  end;

implementation

uses
  Unit2; // unidad del formulario secundario

procedure TForm1.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;

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

El método Notification será llamado cada vez que se agregue o remueva un componente, así que aquí checamos si es el formulario secundario y si está destruyéndose para en tal caso poner la refererencia a nil.

Pero debemos asegurarnos de que la notificación llegue al formulario principal. Para ello basta pedirlo al momento de construirlo:

Código Delphi [-]
// Código para mostrar el formulario secundario

if Form2 = nil then
begin
  Form2 := TForm2.Create(nil);
  Form2.FreeNotification(Self);
end;

Form2.Show;

// Saludos

Última edición por roman fecha: 11-09-2004 a las 00:33:19.
Responder Con Cita