我的应用程序以模态窗体为基础。主窗体通过ShowModal打开一个窗体,这个窗体再用ShowModal打开另一个窗体,因此我们有一堆叠的模态窗体。有时候会出现这样一个问题:当在新窗体中调用ShowModal时,它会被隐藏在之前的窗体后面,而不是显示在顶部。按下alt+tab键后,窗体会回到顶部,但这并不是一个好的解决方案。您是否遇到过这个问题,您是如何处理的?
编辑:
我使用的是Delphi 7。
我的应用程序以模态窗体为基础。主窗体通过ShowModal打开一个窗体,这个窗体再用ShowModal打开另一个窗体,因此我们有一堆叠的模态窗体。有时候会出现这样一个问题:当在新窗体中调用ShowModal时,它会被隐藏在之前的窗体后面,而不是显示在顶部。按下alt+tab键后,窗体会回到顶部,但这并不是一个好的解决方案。您是否遇到过这个问题,您是如何处理的?
编辑:
我使用的是Delphi 7。
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,这样如果模态窗口中发生错误,创建窗口始终会被重新启用。非常抱歉另外添加了一个答案,但我进行了更多的研究,发现我的先前答案(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的解决方案。
procedure DisableProcessWindowsGhosting;
var
DisableProcessWindowsGhostingProc: procedure;
begin
DisableProcessWindowsGhostingProc := GetProcAddress(
GetModuleHandle('user32.dll'),
'DisableProcessWindowsGhosting');
if Assigned(DisableProcessWindowsGhostingProc) then
DisableProcessWindowsGhostingProc;
end;
Self.Enabled := False
代码的情况。Visible
属性设置为 False
,然后使用 .ShowModal();
打开它即可。尝试一下 OnShowForm:
PostMessage(Self.Handle, WM_USER_SET_FOCUS_AT_START, 0, 0);
我发现在多个窗体上使用“始终置顶”标志会导致Z顺序出现问题。您可能还需要BringWindowToTop
函数。
当使用内置的WinAPI(MessageBox
)启动消息框时,我发现传递调用窗口的句柄是必要的,以确保提示始终显示在最上面。