Sobre formularios modales
#1
Escrito 16 septiembre 2010 - 02:37
espero sus comentarion. saludos!
#2
Escrito 16 septiembre 2010 - 02:56
Saludos.
#3
Escrito 16 septiembre 2010 - 03:41
Nop, necesito uno que sea modal, el problema con los forms normales es que si das click fuera de el, este se queda atras de la ventana que seleccones, podria ponerle fsStayOnTop pero no es el efecto que quiero lograr, graciasQuizás lo que buscas es un formulario no modal.
Saludos.
#4
Escrito 16 septiembre 2010 - 04:02
Se supone que un form o ventana modal está hecha para emitir avisos e impedir regresar el "foco" si no es hasta una confirmación (sea positiva o negativa) por parte del usuario.
Un form modal NO debería porqué tener la posibilidad de minimizarse. No está pensado para ello.
Quizá si nos platicas más al respecto podríamos ver en que y como asesorarte. No te enojes si te digo que estoy con escafandra y hay por allí un pequeño error de diseño.
Saludos,
#5
Escrito 16 septiembre 2010 - 04:11
saludos!
#6
Escrito 16 septiembre 2010 - 04:24
Del mismo modo, se se tiene una colección de ventanas modales abiertas, para volver a tener el control deben irse cerrando en el orden inverso.
Si lo que buscas es impedir trabajar en una ventana mientras se esté en otra con "foco" y a la vez que se permita volver al principal para abrir más ventanas. Entonces tus forms deben ser no modales.
Luego debes implementar un mecanismo para llevar el control y el orden de creación/visualización de ventanas abiertas. Esto está ya medianamente implementado: la variable global Application mantiene un array con la ventanas abiertas, e incluso se puede obtener la ordenada Z (es la que da el orden) de cada form.
En segundo lugar este mecanismo se debe vincular a otro que se encargue de deshabilitar todo contro, y operación en las ventanas cuyo Z no corresponda a la ventana actualmente en foco.
De este modo cada vez que se vuelva al form principal (el único que no se vería afectado por este mecanismo de deshabilitado/habilitado) y se cree una nueva ventana la última en tener el foco pase a estar deshabilitada.
Luego, por más que se ponga el foco en las ventanas ya abiertas no tendrían los controles y funciones habilitadas. Deben irse cerrando las ventanas en orden inverso.
¿Se entiende?
Saludos,
#7
Escrito 16 septiembre 2010 - 04:44
entiendo, gracias por tus comentarios.Allí está el tema look, NO SE PUEDE tener el control sobre el principal, sino es hasta CERRAR la ventana Modal.
Del mismo modo, se se tiene una colección de ventanas modales abiertas, para volver a tener el control deben irse cerrando en el orden inverso.
Si lo que buscas es impedir trabajar en una ventana mientras se esté en otra con "foco" y a la vez que se permita volver al principal para abrir más ventanas. Entonces tus forms deben ser no modales.
Luego debes implementar un mecanismo para llevar el control y el orden de creación/visualización de ventanas abiertas. Esto está ya medianamente implementado: la variable global Application mantiene un array con la ventanas abiertas, e incluso se puede obtener la ordenada Z (es la que da el orden) de cada form.
En segundo lugar este mecanismo se debe vincular a otro que se encargue de deshabilitar todo contro, y operación en las ventanas cuyo Z no corresponda a la ventana actualmente en foco.
De este modo cada vez que se vuelva al form principal (el único que no se vería afectado por este mecanismo de deshabilitado/habilitado) y se cree una nueva ventana la última en tener el foco pase a estar deshabilitada.
Luego, por más que se ponga el foco en las ventanas ya abiertas no tendrían los controles y funciones habilitadas. Deben irse cerrando las ventanas en orden inverso.
¿Se entiende?
Saludos,
#8
Escrito 16 septiembre 2010 - 05:03
El punto es que se debe centralizar la creación y visualización de las ventanas en un punto. Y a su vez, cada ventana debe ser capaz de comunicarse con este mecanismo para que este "actualize" el estado general del listado de todos los forms.
En términos abstractos, a mi modo de ver es un caso práctico del principio de "clases amigas" con cardinalidad 1-* (una composición). Puedes ver en acción este principio en TParam y TParans. TParam es una colección de TParams. TParam asume el control de su colección de TParams y se establecen vínculos entre una y otra mandándose mensajes y sincronizandose mutuamente.
Otro posible enfoque que podría ponerse en debate, es la aplicación del patrón Observador; aunque tengo mis reservas si es el caso.
Saludos,
#9
Escrito 16 septiembre 2010 - 06:16
He aquí mi primer acercamiento al tema,
Se cuenta con una clase TAdministradorDeVentanas. Esta clase tendría en forma privada una lista de los forms que se vayan creando y liberando. Algo así:
TAdministradorDeVentanas = class; private ListaDeVentanas: TObjectList; // o cualquier "List" podría servir ... end;
Entre sus obligaciones está de indicar a sus ventanas cual ha de Habilitar y Deshabilitar. Por tanto ya tenemos dos posibles métodos.
procedure HabilitarVentana(OrdenZ: integer); procedure DesHabilitarVentana(OrdenZ: integer);
Te preguntarás porqué trabajar con el número de orden Z y no directamente con la ventana en cuestión. Fácil: Me independizo de estar trabajando con algunas clases puntuales (esto permite que existan muchas posibles clases y no algunos TForm* en particular) y además las ventanas no saben (ni les interesa) saber si existen otras ventanas.
Al disponer de este Z podemos asociarlo con el valor Index del array de ListaDeVentanas. De modo que con esto nos posicionamos en la ventana en cuestión.
Las implementaciones podrían ser cosas como:
procedure TAdministradorDeVentanas.HabilitarVentana(OrdenZ: integer); begin TObject(ListaDeVentanas[OrdenZ]).EventoHabillitar; end;
Estos métodos (Habilitar/Deshabilitar) mandarían un mensaje que todas las clases entenderían... Para ello se puede disponer del uso de evento. Es decir, ambos métodos disparan el método y esto a su vez permite que cada ventana tenga su propia implementación para el habilitado y deshabilitado.
TEventoHabilitar= procedure (...) of Object; TVeventoDeshabilitar = procedure (...) of Object;
Entonces cada Form tendría sus métodos y respuestas propios para el mismo evento.
¿Que otra cosa hace falta? Relacionar las ventanas con este Administrador. No necesariamente el Administrador debería ser el crea las ventanas, pero si el encargado de registrarlas. Por tanto debería tener un método para tal fin:
procedure TAdministradorDeVentanas.RegistrarVentana(Ventana: TObject*, OrdenZ: integer); begin ListaDeVentanas.Insert(Ventana, OrdenZ) // o era inverso el orden de parámetros? ¡No tengo Delphi a mano! end;
O algo por el estilo.
* Estoy haciendolo genérico. Quizá en cierto modo sea posible trabajar con alguna clase en particular, al menos con TForm.
No termina allí la cosa... se ha formado el vínculo desde el administrador hacia las ventanas pero no de ventana al administrador. Todas las ventanas deben tener una referencia al administrador (de otro modo no sería posible interactuar):
TFormX = class(TForm) private FAdministrador: TAdministradorDeVentanas; public property Administrador: TAdministradorDeVentanas write ... read... ... end;
En el momento de registrar, se procede además de establecer esta referencia:
VentanaEnParticular.Administrador := MiAdministrador // el objeto administrador... podría ser global
Ahora listo, ya tenemos una vía de comunicación. Las ventanas cuando reciben foco, o cuando se cierran deberían pedirle su opinión al administrador. Se debe "sincronizar" y quizá actualizar el estado (habilitado/deshabilitado) de alguna.
Ya tenemos otro método para el administrador: Sincronizar. Entonces en los OnActivate y/o OnClose de las ventanas se invocaría a algo como esto:
Administrador.Sincronizar(Self);
Por su parte, el administrador en Sincronizar exploraría su lista, y tendrá acceso a la ventana que le invocó la orden. Evaluando el Orden Z se puede determinar si se le permite o no habilitar (incluso sería más fácil y elemental, sólo aquel Z que sea igual al último en lista se le permite Habilitar).
procedure TAdministradorDeVentanas.Sincronizar(Ventana: T....) var OrdenZ: integer; begin OrdenZ := ObtenerOrdenZ(Ventana) if OrdenZ = ListaDeVentanas.Count - 1 then HabilitarVentana(OrdenZ) else HabilitarVentana(ListaDeVentanas.Count - 1); end;
Esa es más o menos la idea. Esto es sólo un borrrador, algo como para tener una guía. Espero que sea de utilidad para al menos como empezar.
NOTA: No he probado el código. Lo he escrito a mano a medida que redactaba.
Saludos,
#10
Escrito 18 septiembre 2010 - 01:35
Les agradezco muchachos las gracias
Quisiera preguntar si hay alguna novedad o si es necesario repasar algo del borrador.
Podría ser más claro, y evitar hablar de forma genérica, centrar el ejemplo en TForm (creo que sería lo más conveniente) o en alguna clase heredada de TForm que se haya definido como base (muy útil sobre todo se se combina con la herencia visual).
Saludos,