delphi - tokyo - El formulario está oculto detrás de otras formas cuando se llama a ShowModal
delphi versiones (6)
Mi aplicación se basa en formularios modales. El formulario principal abre un formulario con ShowModal, este formulario abre otro con ShowModal, por lo que tenemos formularios modales apilados. A veces surge el problema de que cuando llamamos a ShowModal en forma nueva, se oculta detrás de los formularios anteriores, en lugar de mostrarse en la parte superior. Después de presionar alt + tab, la forma vuelve a la parte superior, pero esta no es una buena solución. ¿Encontraste este problema y cómo lo manejaste?
EDITAR :
Yo uso Delphi 7.
Descubrí que el uso del indicador "Siempre en la parte superior" en más de un formulario causa problemas con el orden Z. Y también puede encontrar la necesidad de la función BringWindowToTop
.
Al abrir un cuadro de mensaje utilizando el WinAPI incorporado ( MessageBox
), he descubierto que es necesario pasar el identificador de la ventana de llamada para asegurarse de que el mensaje aparezca en la parte superior todo el tiempo.
Desde este link , parece que el problema es con la "ventana fantasma" que se introdujo en 2000 / XP. Puede desactivar la función fantasma llamando al siguiente código al inicio.
procedure DisableProcessWindowsGhosting;
var
DisableProcessWindowsGhostingProc: procedure;
begin
DisableProcessWindowsGhostingProc := GetProcAddress(
GetModuleHandle(''user32.dll''),
''DisableProcessWindowsGhosting'');
if Assigned(DisableProcessWindowsGhostingProc) then
DisableProcessWindowsGhostingProc;
end;
El único problema que puedo ver es que causará problemas con la función que permite al usuario minimizar, mover o cerrar la ventana principal de una aplicación que no responde . Pero de esta forma no tiene que cubrir cada llamada con el Self.Enabled := False
.
No mencionaste qué versión de Delphi ...
Las versiones más nuevas de Delphi han agregado dos nuevas propiedades a TCustomForm: PopupMode y PopupParent. Al configurar PopupParent de su diálogo modal en el formulario que está creando ese diálogo, se asegura de que el formulario secundario permanezca en la parte superior de su padre. Por lo general, soluciona el problema que estás describiendo.
Creo que este par de propiedades se agregaron en Delphi 2006, pero puede haber sido en 2005. Definitivamente están en Delphi 2007 en adelante.
EDITAR: después de ver que estás usando Delphi 7, la única sugerencia que tengo es que, en el código que muestra tu formulario modal, deshabilitas el formulario que lo crea y lo vuelves a habilitar a la vuelta. Eso debería evitar que la ventana de creación reciba entrada, lo que puede ayudar a mantener el orden Z correcto.
Algo como esto puede funcionar (no probado, ya que ya no estoy usando D7):
procedure TForm1.ShowForm2;
begin
Self.Enabled := False;
try
with TForm2.Create(nil) do
begin
try
if ShowModal = mrOk then
// Returned OK. Do something;
finally
Free;
end;
end;
finally
Self.Enabled := True;
end;
end;
Si Form2 crea una ventana modal (como ha mencionado), simplemente repita el proceso: deshabilite Form2, cree Form3 y muéstrelo modalmente, y vuelva a habilitar Form2 cuando vuelva. Asegúrate de usar try ... por último, como he mostrado, para que si algo sale mal en el formulario modal, siempre se vuelva a habilitar el formulario de creación.
Perdón por agregar una respuesta por separado, pero he investigado un poco más, y parte de eso indica que mi respuesta anterior (DisableProcessWindowsGhosting) no ayuda. Como no siempre puedo reproducir este problema, no puedo decirlo con certeza.
Encontré una solución que parece apropiada. Hice referencia al código en Delphi 2007 para el método CreateParams y coincide bastante bien (sin tener todo el otro código que maneja PopupMode).
TForm
la unidad debajo de la cual subclases TForm
.
unit uModalForms;
interface
uses Forms, Controls, Windows;
type
TModalForm = class(TForm)
protected
procedure CreateParams(var params: TCreateParams); override;
end;
implementation
procedure TModalForm.CreateParams(var params: TCreateParams);
begin
inherited;
params.WndParent := Screen.ActiveForm.Handle;
if (params.WndParent <> 0) and (IsIconic(params.WndParent)
or not IsWindowVisible(params.WndParent)
or not IsWindowEnabled(params.WndParent)) then
params.WndParent := 0;
if params.WndParent = 0 then
params.WndParent := Application.Handle;
end;
Lo que hago entonces es incluir esta unidad con una unidad de formulario y luego cambiar la clase del formulario (en el archivo de código .pas) de la class(TForm)
a la class(TModalForm)
Funciona para mí, parece estar cerca de la solución de CodeGear.
Simplemente configure la propiedad Visible
del formulario, que desea abrir modal, en False
. Luego puede abrirlo con .ShowModal();
y funcionará
pruébalo OnShowForm:
PostMessage(Self.Handle, WM_USER_SET_FOCUS_AT_START, 0, 0);