Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 10-09-2004
Phacko Phacko is offline
Miembro
 
Registrado: jul 2004
Posts: 157
Poder: 20
Phacko Va por buen camino
Crear Forms en forma DINAMICA

Hola a todos.

Hace un par de días lance un hilo referido como "multiples instancias", que por cierto agradesco a ROMAN por su ayuda. Pues bien trate con lo sugerido y muy bien, pero sucede que el numero de ventanas a emplear no se conoce o no es fijo, la duda es como crearlas dinamicamente y que en su CAPTION aparesca el nombre dado, trate y consegui crearlas con nombres para cada ventana obtenidos de un TEDIT aunque no he podido hacer referencia a ellas, pero (que nunca falta), se presentan los formularios sin CAPTION, ignoro si lo que hice sea correcto, alguien me podrias hechar una mano con eso, esto fue lo que hice para generar las ventanas:

Begin
Name:=Edit1.Text;
TFOrm.Create(Application).Name:=(Name);
TFOrm.Create(Application).Caption:=Name;
TForm.Create(Application).Show;
Application.CreateHandle;
End;
Responder Con Cita
  #2  
Antiguo 10-09-2004
Avatar de vic_ia
vic_ia vic_ia is offline
Miembro
 
Registrado: ene 2004
Posts: 238
Poder: 21
vic_ia Va por buen camino
hola...

no soy muy diestro en esto pero creo que en tu codigo estas en lugar de crear una sola ventana lo que estas haciendo es crear tres ventanas y a cada una le estas "haciendo" algo distinto creo que al menos esta parte del codigo debiera aparecer como

Código Delphi [-]
begin
  ...

  with TFOrm.Create(Application) do
  begin
     Name    := Edit1.Text;
     Caption := Edit1.Text;
     Show;
  end;
  ...
end;
saludos...
Responder Con Cita
  #3  
Antiguo 10-09-2004
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Cita:
Empezado por Phacko
Hola a todos.
Begin
Name:=Edit1.Text;
TFOrm.Create(Application).Name:=(Name);
TFOrm.Create(Application).Caption:=Name;
TForm.Create(Application).Show;
Application.CreateHandle;
End;
Ese es un mal, MAL codigo. Mucho! estas creando 3 ventanas que no
referencian a nada (van a nil), que son separadas y por lo tanto no hacen
lo que quieres y ademas, para que Application.CreateHandle? No lo
necesitas para nada....

Es asi de simple:

Código:
    var
      oForm:TForm;
    begin
      oForm:=TForm.Create(Application);
      oForm.Name:='Hola';
      oForm.Caption:='Hola';
    
    end;
Ahora, ese oForm debe liberarse en algun momento. Si es con una ventana
modal...
Código:
     var
       oForm:TForm;
     begin
       oForm:=TForm.Create(Application);
      try
       oForm.Name:='Hola';
        oForm.Caption:='Hola';
       oForm.ShowModal;
      finally
    	oForm.Release; //se usa release y no free con forms
      end;
     end;
Ahora, el problema que tienes es como administrar las formas? Hay dos
maneras: Usando la referencia Application (observa que application
CONTIENE a oForm) en las colecciones Forms o Components (usando
FindControl('UnNombre') y haciendo cast tambien sirve). Sin embargo, alli
hay otros objetos que no son los que estas haciendo. Realmente, lo que se
hace es crear un administrador en una lista de objetos:

Código:
     var
      oFormas:TObjectList; = Mira en ayudas cual unit se necesita... 
   ObjectList automaticamente libera objetos (llama al free) tonces no
   necesitas preocuparte por objetos perdidos en memoria....
     begin
       oForm:=TForm.Create(Application);
      oFormas.Add(oForm,'Bodega') = Chequee en ayudas, no recuerdo orden
    
       oForm.Name:='Hola';
       oForm.Caption:='Hola';
       oForm.Show;
     
    end;
Con eso, tienes una lista que te permite referenciar como oFormas[i].Caption:='Hola' que era la intencion del codigo normal.
Si haces un helper (una clase de ayuda) puedes poner algo como:

Código:
    function Forma(Nombre:String):TForm;overload;
    function Forma(Indice:Integer);TForm;overload;
Si deseas tener una implementacion mas robusta chequea este excelente
articulo Framework Simple Aplicaciones(ingles):

Es lo que hago tambien y realmente es una forma EXCELENTE de trabajar,
se lo recomiendo a todos. No depende de los controles de DevExpress asi
que no te asustes (y el codigo es funcional: lo puedes usar de base).

Deberias empezar a estudiar sobre Desing Patterns (Patrones de diseño) ya
que aumenta considerablemente la calidad del codigo.....
__________________
El malabarista.

Última edición por mamcx fecha: 11-09-2004 a las 00:23:08.
Responder Con Cita
  #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
Poder: 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
  #5  
Antiguo 11-09-2004
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Si, Screens.Forms es la via rapida.

Sin embargo, el punto que se ve es que una aplicacion GUI tiene un form
principal, entonces crea forms secundarios que:

1- Pueden ser MDIChildren, o pueden ser hijas dentro de una aplicacion SDI,
o puden ser independientes (Owner y parent =nil)
2- Pueden ser modales. A la vez, o son dialogos, o son formas de edicion
3- Pueden ser embeidos (algunos les gusta meter forms dentro de forms, en
vez de usar Frames)
4- Tienen logica de muestra y cerrado muy variable
5- Pueden ser formas de multiple instancia (como los documentos en Word)
o DEBERIAN ser de unica instancia. A la vez, las de unica instancia TAL
VEZ son parte de un esquema MDI... o SDI?
6- Pueden ser ensambladas (ej: Un form contiene los frames de Edicion de
Frame Contacto + Frame campos de cliente + ...)

Las tecnicas tradicionales son ineficientes en el sentido que cada vez que
se hace una forma hija, estamos implementando una de estas ideas, o
muchas mas! Luego, no olvidar que ademas se necesitan sincronizar el
menu, las barra(s) de navegacion... Luego el problema de la reutilizacion.

Es dificil EXTRAER un Form bien hecho, que se necesita en otro proyecto
porque hay muchas dependencias o se olvida como es la logica y las reglas
de creado/destruccion.

Adicionalmente, las interfaces MDI se consideran "obsoletas" por algunos.
De hecho, una forma mas efectiva es usar una interface por tabs, como lo
hace Mozilla Firefox, VS.NET o el mismo Delphi.

Es por eso que es importante el link al framework simple de aplicaciones. La
idea es que uno crea un "modulo" (en mi caso, uso Frames pero igual da con
forms) y un Administrador de modulos se encarga de cubrir TODOS los
casos enumerados anteriormente. Luego, siguiendo el patron de
Factory/Builder, se hace algo como:

Código:
  initialization
    AdministradorModulos.Registrar('Editar Cliente',
 TfrmEditarCliente,
 TCategoria.Create('Editar Cliente','Archivo/Clientes','BarraClientes',IndiceIcono),
 tipInstanciaUnica);
Y en cualquier parte cosas como:

Código:
  AdministradorModulos.Mostrar('Editar Cliente');
 
 resultado:=AdministradorModulos.MostrarModal('Editar Cliente');
 
 AdministradorModulos.Clonar('Editar Cliente');
etc...

Lo cual se encarga de administrar los menus y barras, la logica de creacion
y destruccion declarativamente. Es MUY facil extraer los "modulos" y reusar
en otros proyectos.

Actualmente, tengo una version personalizada basada en esta idea, y
puedo decir que reuso sin problemas modulos con proyectos tan diferentes
como:

- Un ERP (mezcla todo)
- Un IDE de programacion para scripts (mas tipo MDI)
- Un formulario de administracion de los servidores (SDI, 2-3 formas y ya)
- Otros proyectos mas pequeños

Extraigo, reubico y reuso modulos de personalizacion, de claves, de edicion,
etc... sin lios...

La productividad se siente, y no me preocupo en si estoy haciendo bien la
creacion o destruccion, o como se hace todo... adicionalmente, el
administrador de modulos es portable entre D7 y D8 (ASP.NET) y he podido
hacer "transplantes" de componentes (probando con los de Delphi, los de
TMS y DevExpress, actualizando versiones, etc...) con un traumatizmo
minimo....

En fin, es meter TODO el conocimiento que expone Roman (muy bien
explicado) y dejarlo en un framework!
__________________
El malabarista.

Última edición por mamcx fecha: 11-09-2004 a las 00:25:16.
Responder Con Cita
Respuesta



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


La franja horaria es GMT +2. Ahora son las 18:50:58.


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