我的申请基于模式表格。主窗体用ShowModal打开一个窗体,这个窗体用ShowModal打开另一个窗体,所以我们有叠加的模态窗体。有时会出现一个问题,当我们以新的形式调用ShowModal时,它隐藏在以前的表单之后,而不是显示在顶部。按下alt + tab后,表单返回到顶部,但这不是一个好的解决方案。你遇到了这个问题,你是如何处理的?
修改:
我使用Delphi 7。
答案 0 :(得分:23)
你没有提到哪个版本的Delphi ......
较新的Delphi版本为TCustomForm添加了两个新属性:PopupMode和PopupParent。将模式对话框的PopupParent设置为创建该对话框的表单,确保子表单保留在其父对象的顶部。它通常可以解决您所描述的问题。
我认为这两个属性是在Delphi 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;
如果Form2创建了一个模态窗口(正如您所提到的),只需重复该过程 - 禁用Form2,创建Form3并以模态方式显示它,并在返回时重新启用Form2。确保使用try..finally,如我所示,这样如果模态形式出现问题,创建表单将始终重新启用。
答案 1 :(得分:6)
很抱歉添加一个单独的答案,但我做了一些研究,其中一些表明我之前的答案(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;
我所做的是将此单元包含在表单单元中,然后将表单的类(在.pas代码文件中)从class(TForm)
更改为class(TModalForm)
它对我有用,似乎接近CodeGear的解决方案。
答案 2 :(得分:2)
从这个link看来问题出现在2000 / XP中引入的“Ghosting window”。您可以通过在启动时调用以下代码来禁用重影功能。
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
代码覆盖每个来电。
答案 3 :(得分:1)
只需将要打开模式的表单的 Visible
属性设置为 False
。然后,您可以使用 .ShowModal();
打开它,它会起作用。
答案 4 :(得分:0)
PostMessage(Self.Handle, WM_USER_SET_FOCUS_AT_START, 0, 0);
答案 5 :(得分:-1)
我发现在多个表单上使用“Always On Top”标志会导致Z顺序出现问题。您可能还需要BringWindowToTop
函数。
使用内置的WinAPI(MessageBox
)启动消息框时,我发现传递调用窗口的句柄是必要的,以确保提示始终显示在顶部。 / p>