Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 06-02-2018
Neeruu Neeruu is offline
Miembro
 
Registrado: oct 2007
Posts: 484
Poder: 17
Neeruu Va por buen camino
Cool Crear y Destruir Formularios - Forma Correcta

Hola a Todos...

Capaz esta pregunta ya esta contestada en el foro, la busque pero no encontré...


Mi pregunta es la siguiente:
Cual es la manera correcta de crear un formulario?

Planteo el escenario:
  • Tengo una aplicación mdi que tiene su menú principal donde llama a los distintos form que se crean a demanda.
  • Ahora cuando hago click en un item del menú se va a crear un FormX.

  • Ahora cual es la forma correcta:
    1. Definir una variable del Tipo TFormX y Crear el Fomulario.
    2. Utilizar la variable que automaticamente se crea con el Form (FormX:TFormX)

Para Cerrar el formulario , tengo un ToolBar con un TWindowClose.
Pero este no asigna Nil a la variable FormX. ¿Lo correcto seria que asigne nil a la variable FormX en el evento destroy?

Y Porque en el Create de un Form, la Variable FormX es igual a Nil pero Self no? Cual es la diferencia?

Ahora voy a contar porque me surgen estas dudas...
Tengo una app con casi 300 formularios. en la mayoria de los formularios, en el create del mismo llamo a un procedimiento que me pinta los componentes de x color.
Hasta acá sin problemas. Pero resulta que ahora he tenido que agregar nuevos formularios y se da que aveces abro este form nuevo (FormX) y en el procedimiento que pinta los componentes me arroja un access violation. O se me da que abro un determinado form y luego el FormX y arroja el AV.

Llevo mas de una semana tratando de encontrar el porque con estos nuevos formularios se produce el error y no encuentro. Ya cree un proyecto nuevo, probé en otra pc, hice los formularios desde 0... Y nada el error persiste...

Entonces empece a ver mas detalladamente y note que (Yo siempre utilice la variable Form, que crea automáticamente el formulario) la primera ves que entra el formulario al procedimiento que pinta FormX = Nil, ahora la segunda vez ( Osea, lo cierro con el botón de cerrar TWindowCloe) y si lo abro de nuevo FormX tiene cosas adentro, no viene con Nil.

Puse FormX := Nil en el evento destroy del FormX y el problema se soluciono.
Ahora me queda la gran incógnita y es lo que me come la cabeza, de porque el error solo con esos formularios.

Llegue a pensar a al pasar algún tamaño de ejecutable o uso de memoria a lo mejor cambia la administración y por eso surge ahora el error.. la verdad no se...
Y por eso es que viene mi pregunta... ahora estoy pensando que a lo menor la forma en la que estoy creando y destruyendo los formularios no es la correcta, aunque esto no me responda porque en 299 Formularios no da el error y en el 300 si...(Puse estos mismos formularios en proyectos aun mas grandes y el error no se da)
__________________
Saluda Atte Neeruu!!! :)

Última edición por Neeruu fecha: 06-02-2018 a las 23:37:35.
Responder Con Cita
  #2  
Antiguo 06-02-2018
Neeruu Neeruu is offline
Miembro
 
Registrado: oct 2007
Posts: 484
Poder: 17
Neeruu Va por buen camino
Todo esto viene a raiz de lo publicado en este post:
http://www.clubdelphi.com/foros/showthread.php?t=92600
__________________
Saluda Atte Neeruu!!! :)
Responder Con Cita
  #3  
Antiguo 07-02-2018
Neeruu Neeruu is offline
Miembro
 
Registrado: oct 2007
Posts: 484
Poder: 17
Neeruu Va por buen camino
Hola... Como crean sus formularios....?????
__________________
Saluda Atte Neeruu!!! :)
Responder Con Cita
  #4  
Antiguo 07-02-2018
Avatar de ElKurgan
[ElKurgan] ElKurgan is offline
Miembro Premium
 
Registrado: nov 2005
Posts: 1.232
Poder: 20
ElKurgan Va camino a la fama
Para empezar, yo uso poco los formularios tipo DMI, más que nada porque en el trabajo diario no me hacen falta. Pero tengo entendido que cuando creas una ventana "hija" en un MDI se crea, pero cuando la cierras NO SE DESTRUYE, sino que se esconde. En estos casos, revive con un "Show" y no con un nuevo create.

Cuando creo formularios "modales", elimino de estos la variable "Formx: TFormx" que se crea automáticamente. Prefiero crearlos y liberarlos yo mismo desde código (No hace falta decir que hay que quitarlos de la parte "Autocreate" de las opciones del proyecto).

De todas formas no está de más echar un vistazo a La cara oculta de Delphi 4 que, en el capítulo 13, tiene un extenso tutorial sobre "Técnicas de Gestión de Ventanas"

Saludos
Responder Con Cita
  #5  
Antiguo 07-02-2018
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.233
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por Neeruu Ver Mensaje
Hola... Como crean sus formularios....?????
Comentas muchas cosas y es un tema delicado.
Lo primero que te diría es que elimines la variable que se crea automáticamente en cada formulario, porque es una variable global que suele dar problemas. El que has comentado tú y otros similares.
Crea tus propias variables de formulario donde las necesites. Una solución si debes reaprovecharlas es ponerlas a NIL cuando se destrruye el formulario tal y como has hecho.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #6  
Antiguo 07-02-2018
Neeruu Neeruu is offline
Miembro
 
Registrado: oct 2007
Posts: 484
Poder: 17
Neeruu Va por buen camino
Naftali, gracias...

Conoces alguna documentación donde se hable lo que estoy preguntando...

Ya mismo empezare a corregir el código de mi proyecto.... tengo para rato ...

Si sabes de algún material de lectura, bienvenido...

Saludos.
__________________
Saluda Atte Neeruu!!! :)
Responder Con Cita
  #7  
Antiguo 07-02-2018
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.233
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Específicamente de esto no, pero en el FTP tienes bastantes manuales de Delphi. Algunos incunables como "La Cara Oculta de Delphi".
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #8  
Antiguo 08-02-2018
Avatar de gatosoft
[gatosoft] gatosoft is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Bogotá, Colombia
Posts: 833
Poder: 21
gatosoft Va camino a la fama
Buen día,

Personalmente estoy de acuerdo con lo expresado por Roman en el post #9 del hilo que enlazo aquí

Sin embargo hay una solucion que yo utilizo para evitar lidiar con los FreeAndNil, "releases" mal ubicados.

y es la siguiente:

1) Creo un Tform1 que es el MDIform y un tform2 que es el MDIChild
2) Elimino la variable automática que crea el Tform2 (form2), como sugiere ElKurgan
3) en el evento onclose del Tform2 agrego la linea: Action:= caFree;
4) Para efectos de la prueba agrego dos botones u opciones de menú en el form1.

a) el primer boton instancia formularios TForm2 sin asignarlos a variables (pues se liberarán con el Onclose.

Código Delphi [-]
procedure TForm1.NuevoFormulario1Click(Sender: TObject);
begin
  With Tform2.Create(Self) do
     Begin
       inc(contador);
       Caption:= IntTostr(contador);
       show;
     End;
end;

b) el segundo crea un formulario asignado a una única variable llamada MyFormX

Código Delphi [-]
procedure TForm1.formX1Click(Sender: TObject);
begin
  if not Assigned(MyFormX) then
     begin
       MyFormX:= TForm2.Create(Self);
       MyFormX.Show;
     end else
         MyFormX.BringToFront;
end;


PERO...!!! éste útlimo código solo funcionará una vez pues el Action:=caFree, libera la memoria pero la variable queda asignada por tanto Assigned(MyformX) solo será falso la primera vez...

entonces aqui utilizo un truco que me parece bastante seguro: Utilizo una variable de clase para indicar si el formulario está instanciado o no

Código Delphi [-]
unit Unit2;

type
  TForm2 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
    Class var EstoyOcupado: String;
  end;

y en el Form1 cambio el llamado al boton:
Código Delphi [-]
procedure TForm1.formX1Click(Sender: TObject);
begin
  if not Assigned(MyFormX) or (TForm2.EstoyOcupado <> 'SI') then
     begin
       MyFormX:= TForm2.Create(Self);
       TForm2.EstoyOcupado:='SI';
       MyFormX.Show;
     end else
         MyFormX.BringToFront;
end;


De ésta manera quedan asi los códigos

Form1:
Código Delphi [-]
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus;

type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    Nuevoform1: TMenuItem;
    NuevoFormulario1: TMenuItem;
    formX1: TMenuItem;
    procedure NuevoFormulario1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure formX1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    contador: Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Unit2;

Var MyFormX: TForm2;

procedure TForm1.FormCreate(Sender: TObject);
begin
  contador:=0;
end;

procedure TForm1.formX1Click(Sender: TObject);
begin
  if not Assigned(MyFormX) or (TForm2.EstoyOcupado <> 'SI') then
     begin
       MyFormX:= TForm2.Create(Self);
       TForm2.EstoyOcupado:='SI';
       MyFormX.Show;
     end else
         MyFormX.BringToFront;
end;

procedure TForm1.NuevoFormulario1Click(Sender: TObject);
begin
  With Tform2.Create(Self) do
     Begin
       inc(contador);
       Caption:= IntTostr(contador);
       show;
     End;
end;

end.

Form2:
Código Delphi [-]
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm2 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
    Class var EstoyOcupado: String;
  end;

implementation

{$R *.dfm}

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  TForm2.EstoyOcupado:='';
  Action:= caFree;
end;

end.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
forma de programar no se si es la correcta ? gulder MySQL 4 05-04-2016 18:49:51
Liberar Tlist de forma correcta BDWONG Varios 3 01-11-2014 18:28:46
Forma correcta de conectar a la base.. linuxtin Conexión con bases de datos 4 19-07-2012 21:30:20
Crear formularios de forma dinamica istradlin Lazarus, FreePascal, Kylix, etc. 4 06-12-2007 16:30:40
Como destruir o liberar una forma maguib Varios 1 11-03-2005 20:39:02


La franja horaria es GMT +2. Ahora son las 14:29:22.


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
Copyright 1996-2007 Club Delphi