PDA

Ver la Versión Completa : Formularios modales y no modales


sur-se
30-07-2008, 12:46:53
Hola. Tengo una aplicación desarrollada en Delphi 5 en la que existen formularios modales y no modales, en una clásica aplicación MDI.
El tema es que es que dispongo de una serie de formularios "base" a partir de los cuales, por herencia, se van creando los formularios definitivos que verá el usuario, de manera que se encapsule en esos formularios base las caraterísticas y funciones comunes a todos los formularios hijos.

La cuestión es que en determinadas circunstancias necesitaría que un formulario, cuyo diseño base es no modal (child window) y por ello el formulario heredero es también no modal, pueda ser abierto en modo modal. Esta circunstancia me ocurre cuando tengo abierta una pantalla modal y necesito abrir encima otra pero resulta que procede de una no modal.
Un solución simple sería crear el mismo formulario "base" con un formulario de tipo modal y ya está, pero claro eso supone la duplicación innecesaria del código y la repetición del formulario base con los posibles futuros errores o mejoras que tendría que repetir en los dos formularios "base" y heredados.

Así pues, ¿es posible abrir una pantalla no modal en modo modal en un momento dado?

Un saludo y gracias por la ayuda.

coso
30-07-2008, 16:57:49
¿es posible abrir una pantalla no modal en modo modal en un momento dado?

hola,
siempre que mantengas el 'showmodal' accesible, podras llamarla modalmente. Prueba de hacer, en los tipos de form que tu llamas 'no modales', un showmodal, a ver que te ocurre...

sur-se
30-07-2008, 17:22:17
Hola. Pues no. Da multitud de errores de violación de acceso y demás que no están relacionados con la programación del formulario "base" y no funciona.

Es lo primero que probé antes de poner el post.

coso
30-07-2008, 17:26:59
entonces prueba de llamarlo como una clase modal anterior, incluso como clase form inicial

(forma_de_tipo_no_modal as TForm).ShowModal;

Lo que me extraña es ¿porque eliminas el metodo showmodal desde la TForm original?, asi siempre tendras los dos tipos de llamada. Me refiero...¿es necesaria la diferenciacion de modales-no modales en tus definiciones de clase?

roman
30-07-2008, 17:27:14
Tal como dice coso, el carácter modal no depende de la ventana en sí, sino de lo forma en que se muestra, bien sea usando Show o ShowModal.

Sin embargo, el problema puede estar en que tu formulario sea fsMDIChild, pues en tal caso, el uso de ShowModal no es posible.

Yo lo que haría es dejar el formulario como fsNormal para poderlo mostrar modalmente con ShowModal, y cuando quieras mostrarlo como foumulario hijo:


var F: TFormHijo;

begin
F := TFormHijo.Create(...);
F.FormStyle := fsMDIChild;
// F.Show;
end;


// Saludos

sur-se
30-07-2008, 18:04:02
Hola coso. Yo el método showmodal no lo oculto ni elimino ni nada. Simplemente es que si tu lo ejecutas sobre un form no modal, da errores en la ejecución. Nada más.

Efectivamente, como comenté al principio el formulario base es de tipo no-modal, es decir, fsMDIChild ya que en casi todos los casos la ventana se abre en modo NO-MODAL.
El problema es que cuando una vez necesito que se ejecute en MODAL, ahí está el problema.
Una posibilidad sería como dice roman pasarlo a fsNormal y en la creación y apertura de la pantalla cambiarle el formstyle, aunque no tengo claro que repercusiones tendrá en el funcionamiento. Tendré que hacer pruebas.
Estas son las cosas que las planteas desde el prinpicipio de una forma que en el 99% de los casos es como se planteó hasta que llega ese 1% que va y te lo estropea ...
Un saludo.

coso
30-07-2008, 19:55:47
ok, por lo que pusiste entendi que definias completamente la clase.
Si lo unico que haces es cambiar la propiedad FormStyle, entonces lo de Roman te deberia funcionar. Ya comentaras algo.

sur-se
31-07-2008, 08:18:48
Pues no. Tampoco funciona. Como tengo un constructor propio de la form "base" he probado también en cambiar ahí la propiedad formstyle, antes de la inicialización de los componentes y después de ella (inherited), y nada sigue igual. Creo que no hay forma de hacerlo.
Al final optaré por una clase base que sea de tipo modal y tendré el código duplicado. He probado los múltiples cambios y no va.
Un saludo.

sur-se
01-08-2008, 10:59:43
Investigando un poco el tema, porque antes no se me había dado esta cuestión, he visto que las únicas diferencias entre un form de tipo fsNormal y fsMDIChild está en el FormStyle y en el Visible. En el caso de formularios modales (fsNormal), el Visible es False, mientras que en los fsMDIChild el visible es true. Esto, que parece una tontería, es la diferencia que hace que no pueda abrirse un formulario no modal como modal.
Si bien, se podría hacer algo del tipo:


with Tform_no_modal.create(self) do
begin
FormStyle:=fsNormal;
Showmodal;
Free;
end;


El problema es que sigue dando el error de no se puede poner visible un formuario no modal.
Si tratamos de poner el Visible:=false antes del FormStyle o después, pero antes del showmodal, se produce el mismo error.

Otra alternativa que he probado es a definirme mi propio constructor para la form, de manera que tratemos de poner el estilo y el visible antes del create, de la forma siguiente:


unit formulario_no_modal;
..
constructor crearmodal;
...
constructor TForm_no_modal.crearmodal;
begin
FormStyle:=fsNormal;
Visible:=false;
inherited; // Para construir el resto de los objetos
end;


Pero esto tampoco funciona pues da el mismo problema. Así pues, no parece haber manera de abrir un formulario en modal que esté definido como no modal en tiempo de diseño. Al menos ya no se me ocurren más intentos que hacer.

Un saludo.

coso
01-08-2008, 12:39:46
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.FormStyle := fsNormal;
Form2.Hide;
Form2.SHowmodal;
Form2.Hide;
Form2.FormStyle := fsMDIChild;
end;


siendo Form1 MDIForm y Form2 MDIChild en tiempo de diseño, a mi este codigo me funciona...

coso
01-08-2008, 12:46:19
Tienes un error de concepto : no existen forms 'modales' o 'no modales', es segun como se las llama, como te hemos comentado. Ten en cuenta que no se puede llamar modalmente una form MDIChild porque seria ilogico, ya que una MDIChild se supone que es para que existan varias dentro de otra principal, sin ninguna con el foco fijado en ella y sin que ninguna tenga preferencia, y un showmodal es para que una tenga preferencia y foco fijo. Vamos, que los dos conceptos son autoexcluyentes. Pero si cambias la propiedad formstyle...pues ya esta. Ten en cuenta que si esta visible, es ilogico llamar a que se muestre, por lo tanto, las escondemos antes de llamarla.

roman
01-08-2008, 16:54:56
Creo, sur-se, que te estás haciendo demasiados líos con esto. Toma en cuenta que de por sí es raro, al menos visto desde fuera, que una ventana deba mostrarse unas veces como modal y otras como MDIChild, como ya te lo comento coso, las ventanas MDIChild están pensadas para ser no modales.

Ahora, si te fijas en el mensaje #5 (http://www.clubdelphi.com/foros/showpost.php?p=304441&postcount=5), comenté que dejaras el formulario como fsNormal de inicio y sólo cuando quisieras mostrarlo como MDChild, le cambiaras el estilo. Alrevés no es tan sencillo, porque si el formulario es MDIChild, automáticamente se va a hacer visible y por ello el error al usar ShowModal.

// Saludos

sur-se
04-08-2008, 08:03:51
Hola. Gracias a todos por la ayuda.
El problema de hacerlo como roman dice, es decir, ponerlo como Modal (fsNormal) y abrirla como MDIChild cuando lo necesite no lo puedo hacer, por eso he seguido con el tema. El motivo es que tengo más muchos sitios en los que tendría que cambiar la llamada a la pantalla ya que está puesta como mdi child y tendría que hacer los cambios correspondientes, y como el hecho de abrirlo en Modal es sólo para uno o dos sitios, era más sencillo.
Probaré lo que me comentais.
Gracias de nuevo.

coso
04-08-2008, 09:42:29
mira, usa esta funcion,


function MDI_a_Modal(f : TForm) : TModalResult;
var
mr : TModalResult;
begin
try
f.FormStyle := fsNormal;
f.Hide;
mr := f.SHowmodal;
f.Hide;
f.FormStyle := fsMDIChild;
except
mr := mrCancel;
end;
MDI_a_Modal := mr;
end;