PDA

Ver la Versión Completa : Mdi no repetir ventanas abiertas


José Luis Garcí
01-03-2009, 16:23:17
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

Tform.create(self);

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

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:


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í:

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;

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.


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 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?


procedure FormHijoClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
FormHijo := nil;
end;


Y para abrir el formulario hijo:


if not Assigned(FormHijo) then
FormHijo := TFormHijo.Create(nil);


// Saludos

Casimiro Notevi
03-03-2009, 00:50:10
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 [-] (http://www.clubdelphi.com/foros/#)Error(3, TForm(Fnombre).name)

Bueno, es que es un procedimiento mio, algo así:

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á.

FindShowForm function


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

Unit
AppUtils

Declaration
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:

procedure MainForm.ShowFormItemClick(Sender: TObject);
begin
FindShowForm(TForm1, '');
end;

Neftali [Germán.Estévez]
03-03-2009, 17:50:39
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
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:


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:

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

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

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;