Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Mdi no repetir ventanas abiertas (https://www.clubdelphi.com/foros/showthread.php?t=63756)

José Luis Garcí 01-03-2009 16:23:17

Mdi no repetir ventanas abiertas
 
Hola compañeros, llevo un tiempo desconectado del club por motivos personales y laborales, me guataria que me ayudaseis con el siguiente problema que tengo:

Tengo una Form padre y una serie de foms hijos, que creo según se solicita, no tengo problemas a la hora de crarlos, mediante

Código Delphi [-]
Tform.create(self);

Ni al destruirlos mediante el siguiente codigo en el evento Onclose del Form

Código Delphi [-]
Action:=Canfree;

El problema es que no se como evitar que si e abierto el Form de clientes lo pueda abrir de nuevo .

Casimiro Notevi 01-03-2009 16:55:23

Tienes varias formas de hacerlo, yo normalmente lo hago así:
Tengo una unit de funciones comunes y entre ellas está esta:

Código:

function AbreForm (Cclase : TFormClass; bMostrar: boolean; var Fnombre) : boolean;
(* bMostrar indica si el formulario se visualizará o no *)
var
  F : TForm;
begin
  result := true;
  F := Application.FindComponent (copy(cClase.ClassName,2,255)) as TForm;
  if assigned(F) and bMostrar then
  begin
    F.Show;
  end
  else
  begin
    try
      Application.CreateForm (Cclase, Fnombre);
      if bMostrar then
        (Application.FindComponent (copy(cClase.ClassName,2,255)) as TForm).Show;
    except
      if assigned(TForm(Fnombre)) then
        Error(3, TForm(Fnombre).name)
      else
        Error (3,'');
      result := false;
    end;
  end;
end;

Y la llamada sería algo así:
Código:

AbreForm(TFentradaUsuario,False,FentradaUsuario);
FentradaUsuario.ShowModal;

Si ya está creada (asignada), entonces se abre. Si no lo está, se crea.
También se puede hacer directamente;
Código:

AbreForm(TFentradaUsuario,True,FentradaUsuario);

José Luis Garcí 01-03-2009 17:03:53

Gracias por tu rápida respuesta Casimiro, me parase una idea genial lo de agregarla a un unit de funciones, lo probare a partir de mañana y te digo como me fue. Un día de estos tendrimaos que juntar las funciones que usamos en un único fichero de todos los miembros, nos ayudaría mucho.

Neftali [Germán.Estévez] 02-03-2009 08:57:34

Creo que para esto se pueden usar las propiedades MDIChildCount y MDIChildren de TForm.

Por ejemplo para un form2 se puede preguntar si ya está entre los que están creados/abiertos.

Código Delphi [-]
var
  i:Integer;
begin

  // Revisar los formularios...
  for i := 0 to (Self.MDIChildCount - 1) do begin
    if (Self.MDIChildren[i] = form2) then begin
      // Nada
      MessageDlg('Ya está abierto...', mtInformation, [mbOK], 0);
      Exit;
    end;
  end;

  // Si llega a quí es que hay que crearlo.
  form2 := TForm2.Create(Self);

Puedes colocarlo dentro de un procedimiento para automatizarlo...

Casimiro Notevi 02-03-2009 10:25:29

Todos los días se aprende algo :eek:, nunca me había interesado por saber para qué servían esas propiedades tan "raras", incluso alguna vez he llegado a implementar algo parecido usando la propiedad 'tag'... :D

José Luis Garcí 02-03-2009 20:50:33

Personalmente me gusta la idea de trabajar con una funcion, pero también admito que es más lógico el método de Neftali para las MDI. De Todas maneras me da un error en la funcion Casimiro, imagino que por culpa de algún uses?, el error es Operator semi colon justo en
Código Delphi [-]
Error(3, TForm(Fnombre).name)
, si me podéis decir cual es el problema y como se podría, si es posible convertir el método proporcionado por Neftali a una funcion. Muchas Gracias

roman 02-03-2009 20:58:24

¿Y pr qué no algo como esto?

Código Delphi [-]
procedure FormHijoClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
  FormHijo := nil;
end;

Y para abrir el formulario hijo:

Código Delphi [-]
if not Assigned(FormHijo) then
  FormHijo := TFormHijo.Create(nil);

// Saludos

Casimiro Notevi 03-03-2009 00:50:10

Cita:

Empezado por José Luis Garcí (Mensaje 339882)
De Todas maneras me da un error en la funcion Casimiro, imagino que por culpa de algún uses?, el error es Operator semi colon justo en Código Delphi [-]Error(3, TForm(Fnombre).name)

Bueno, es que es un procedimiento mio, algo así:
Código:

procedure Error (iNumError : integer; cTexto : string);
var
  cE : string;
begin
  case iNumError of
    0 : cE :=  cTexto;
    1 : cE :=  cTexto;
    2 : cE :=  cTexto;
    3 : cE := 'Error al crear el formulario ' + cTexto;
    4 : cE := 'Error al cerrar el formulario ' + cTexto;
...
...


rcarrillom 03-03-2009 17:29:26

Olvídense de escribir más código ;), las Rx tienen la función FindShowForm en su unidad AppUtils que ya lo implementa; las Rx ya fueron integradas en las jcl y jvcl, si tienen éstos paquetes instalados, pues ya está.

Cita:

FindShowForm function


--------------------------------------------------------------------------------

Unit
AppUtils

Declaration
Código Delphi [-]
function FindShowForm(FormClass: TFormClass; const Caption: string): TForm;

Description
FindShowForm returns the windowed Delphi's form whose class is identified by the specified class name FormClass and (or) window caption passed as Caption.

If FormClass is not the name of the class of an existing form, FindShowForm creates new form by calling Application.CreateForm. For found or created form the Show method is called.

FindShowForm example:

Código Delphi [-]
procedure MainForm.ShowFormItemClick(Sender: TObject);
begin
FindShowForm(TForm1, '');
end;


Neftali [Germán.Estévez] 03-03-2009 17:50:39

Cita:

Empezado por rcarrillom (Mensaje 340014)
Olvídense de escribir más código ;), las Rx tienen la función FindShowForm en su unidad AppUtils que ya lo implementa; las Rx ya fueron integradas en las jcl y jvcl, si tienen éstos paquetes instalados, pues ya está.

Ya estará, pero me parece un poco exagerado añadir las Rx al proyecto (:o) o la JCL+JVCL (:o:(:eek::eek:) para no programar 4 líneas de texto.

Para pensárselo... :D:D:D

roman 03-03-2009 17:52:38

Cita:

Empezado por rcarrillom
las Rx tienen la función FindShowForm

Pues sí, pero tanto FindComponent como FindShowForm hacen un ciclo en búsqueda del formulario. Ese ciclo no es necesario si se asegura poner la referencia al formulario en nil. Sí, sí, ya sé, apenas ganaremos medio milisegundo, pero algo es algo :D

// Saludos

José Luis Garcí 03-03-2009 18:19:59

Gracias a todos por vuestras respuestas, la verdad es que :D Perdón pero acojonais, si hay tantas respuestas para una solucion tan simple y yo con más de 20 libros de delphi, la busqueda en el club y en google, no doy pie con bola es que soy muy malo y estoy muy desfasado.

Esto de programar para no quedarme desfasado, me esta costando y no se si me merece la pena seguir, por que noto que cada vez tengo más conceptos a los que no doy pie con bola. Con lo Facil que ere programar con clipper y lo controladito que lo tenia.:p

Casimiro Notevi 04-03-2009 00:54:58

Clipper era pequeñito en comparación con los sistemas actuales, no son comparables, aunque finalmente sirvan para lo mismo, para guardar y extraer información.
No debes rendirte, escoge la forma que te resulte más cómoda o más clara, o más simpática, o más simple, o más elegante, o más enrevesada... da igual, mientras funcione :)

José Luis Garcí 04-03-2009 20:45:37

Gracias Amigo, llevo años peleándome con delphi y no pienso abandonarlo, aunque me tienta cosmos y velneo, pero no dejando delphi.

AzidRain 04-03-2009 22:06:52

Yo uso esta función simplona que crea un formulario MDI o lo muestra si ya existe:

Código Delphi [-]
Type
 TFormClass = class of TForm;

Procedure CreateMDI(Owner:TForm;BaseClass:TFormClass;  FormVar:TForm);
var
found:Boolean;
i:integer;

begin
  found := FAlse;
  // recorremos el array de ventanas hijas
  For i:= 0 To Owner.MDIChildCount-1 Do
    If Owner.MDIChildren[i] is BaseClass Then
    Begin
      Owner.MDIChildren[i].Show;
      found := True;
    End;
  if not found then
    Application.CreateForm(BaseClass,FormVar);
end;

forma de Uso:
Código Delphi [-]
 CreateMDI(Application.MainForm, TMiForm, FMiForm);

Y voilá...reconozco que esta medio chapuceron pero hasta ahora me ha funcionado bien y simple, si la ventana no existe la crea, si ya existe la muestra.

jconnor82 05-03-2009 08:02:05

Ya q todos estan colocando sus rutinas ponga la mia :D

No modal

Código Delphi [-]
procedure FormShowEx(AOwner: TComponent; AClass: TFormClass);
var
  Form: TForm;
  I: Integer;
begin
  {Verifica si el formulario ha sido creado anteriormente}
  Form := nil;
  for I := 0 to Screen.FormCount - 1 do
    if Screen.Forms[i].ClassType = AClass then
    begin
      Form := Screen.Forms[i];
      Break;
    end;
  if Form = nil then
    Form := AClass.Create(AOwner);
  Form.Show;
  Form.BringToFront;
end;

Modal

Código Delphi [-]
function FormShowModalEx(AOwner: TComponent; AClass: TFormClass): Integer;
var
  I: Integer;
begin
  for I := 0 to Screen.FormCount - 1 do
    if Screen.Forms[i].ClassType = AClass then
    begin
      Screen.Forms[i].Show;
      Screen.Forms[i].BringToFront;
      Result := mrNone;
      Exit;
    end;

  with AClass.Create(AOwner) do
    try
      Result := ShowModal;
    finally
      Free;
    end;
end;


La franja horaria es GMT +2. Ahora son las 15:47:11.

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