我的应用程序基于模态窗体。主窗体用ShowModal打开一个窗体,这个窗体用ShowModal打开另一个窗体,所以我们堆叠了模态窗体。有时会出现一个问题,当我们以新形式调用ShowModal时,它隐藏在以前的表单之后,而不是显示在顶部。按alt + tab后,窗体回到顶部,但这不是一个好的解决方案。你遇到了这个问题,你是如何处理它的?当调用ShowModal时,窗体隐藏在其他窗体的后面
编辑:
我用Delphi 7
我的应用程序基于模态窗体。主窗体用ShowModal打开一个窗体,这个窗体用ShowModal打开另一个窗体,所以我们堆叠了模态窗体。有时会出现一个问题,当我们以新形式调用ShowModal时,它隐藏在以前的表单之后,而不是显示在顶部。按alt + tab后,窗体回到顶部,但这不是一个好的解决方案。你遇到了这个问题,你是如何处理它的?当调用ShowModal时,窗体隐藏在其他窗体的后面
编辑:
我用Delphi 7
你没有提到的Delphi的版本...
较新版本的Delphi增加了两个新的属性,以TCustomForm:PopupMode和PopupParent。将模态对话框的PopupParent设置为创建该对话框的窗体可确保子窗体保持在其父窗体之上。它通常可以解决你所描述的问题。
我认为这对属性是在2006年德尔福中添加的,但可能是2005年。它们绝对存在于Delphi 2007及更高版本中。
编辑:在看到您使用Delphi 7后,我唯一的建议是,在显示您的模式窗体的代码中,禁用创建它的窗体并在返回时重新启用。这应该防止创建窗口接收输入,这可能有助于保持Z顺序正确。
像这样的东西可能工作(未经测试,因为我不再使用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;
如果窗体2创建了一个模态窗口(如你所提到的),只是重复这个过程 - 禁用窗体2 ,创建Form3并以模态方式显示它,并在返回时重新启用Form2。请确保按照我所示的方式使用try..finally,以便在模态窗体中出现错误时始终重新启用创建窗体。
我发现,使用“总在最前面”标志上不止一种形式导致与Z顺序问题。你也可能发现需要BringWindowToTop
功能。
使用内置的WinAPI(MessageBox
)启动消息框时,我发现必须传递调用窗口的句柄以确保提示始终显示在最前面。
查看我对Lars D.所有者(或父母)的回复与所描述的问题无关。这个问题是TAppication隐藏窗口从任务栏中移除的后果;它引起了儿童表格在Z顺序中失去适当位置的问题,这就是PopupParent和PopupMode被创建来解决的问题。 – 2009-10-28 19:05:44
不够公平......在进一步检查时,我意识到我在考虑使用Windows.MessageBox函数并传递调用窗口的句柄,以确保MessageBox显示在调用者的顶部 - 我正在考虑的是“父母”。将编辑我的答案来反映这一点。 – 2009-10-28 21:37:39
从这个link看来,问题出现在2000/XP中引入的“重影窗口”。您可以通过在启动时调用以下代码来禁用重影功能。
procedure DisableProcessWindowsGhosting;
var
DisableProcessWindowsGhostingProc: procedure;
begin
DisableProcessWindowsGhostingProc := GetProcAddress(
GetModuleHandle('user32.dll'),
'DisableProcessWindowsGhosting');
if Assigned(DisableProcessWindowsGhostingProc) then
DisableProcessWindowsGhostingProc;
end;
,我可以看到的唯一问题是,它会导致与允许用户minimize, move, or close the main window of an application that is not responding的功能问题。但通过这种方式,您不必使用Self.Enabled := False
代码覆盖每个呼叫。
如果真的有效,那会很好。谢谢。这个问题困扰了我很长一段时间。然而,如果表单具有WS_POPUP风格并且“所有者”是正确的窗口,那么即使是“幻影”形式也不允许将Z-order切换到它的所有者之下,因此没有机会一个突然消失的模态对话框。“我没有看到任何表单中的所有者参考。 – LukLed 2009-11-18 19:28:45
对不起,添加了一个单独的答案,但我做了一些更多的研究,其中一些表明我以前的答案(DisableProcessWindowsGhosting)没有帮助。由于我不能总是重现这个问题,我不能肯定地说。
我找到了合适的解决方案。我在Delphi 2007中引用了CreateParams方法中的代码,并且它非常接近(没有处理PopupMode的所有其他代码)。
我创建了下面的单元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;
我要做的则是包括本机与形式的单元,然后更改从class(TForm)
窗体类(在.PAS代码文件)class(TModalForm)
它的工作对我来说,似乎接近CodeGear的解决方案。
只需设置形式的Visible
财产,要开模,到False
。然后你可以打开它.ShowModal();
它会工作。
感谢添加的版本。如果你在问题的文字或标签中加入了它,它会有所帮助。 :-) – 2009-10-28 19:07:03
我没有设置适当的标签,然后添加编辑:) – LukLed 2009-10-28 19:08:46
只要你把它放在什么地方,它就可以。它不一定必须位于其中一个标签中,只要它位于某个问题的主题或文本中即可。这可以让人们在回答时知道你有什么功能。 :-) – 2009-10-28 19:33:26