我正在使用一个旧的 Delphi 项目开发 Delphi 11.2,在
Application.MainFormOnTaskBar
的介绍之前,所以默认情况下它被设置为 False
。我尝试将以下行添加到项目的 .dpr
文件中 Application.Initialize;
之后,就像 Delphi 文档 建议的那样:
Application.MainFormOnTaskBar := True;
我的目标是模仿所有其他现代 Windows 应用程序,并在 Windows 任务栏上显示当前 MainView 的预览。虽然我的更改确实实现了这一点,但它也导致了模态对话框的不良行为。
确定模式对话框的父级和窗口 z 顺序的逻辑与具有
Application.MainFormOnTaskBar := False;
的应用程序不同。现在,这经常会在应用程序中的其他浮动窗口后面显示模式对话框,从而使模式对话框不可单击并锁定应用程序。
许多其他人也看到了相同的行为,并且在 Delphi 的文档中进行了说明。不幸的是,我能找到的关于恢复旧 z 排序的最有用的信息都有死链接,因为它是从 2007/2008 年引入
Application.MainFormOnTaskBar
的时候开始的。旧的论坛帖子指出使用 PopupParent
、PopupMode
和 Application.ModalPopupMode
来重现旧的模式对话框行为。我在这些方面没有取得任何成功。
我发现有效的一个解决方法是在表单的
Params.WndParent := 0;
中设置 CreateParams()
。然而,我更愿意为所有模式对话框找到一个通用的解决方案,因为我使用内置的 VCL 方法,如 ShowMessage()
和系统对象 TMsgDlgType
来显示简单的模式对话框。
我希望旧的模式对话框 z 排序并让实时 MainView 预览出现在 Windows 任务栏上。有没有新的最佳方法来实现这一目标?自推出以来,此功能有任何进步吗?我可以在不设置
Application.MainFormOnTaskBar
的情况下在 Windows 任务栏上显示实时 MainView 预览吗?
编辑:
以下是有关项目整体流程的更多信息
Application.MainFormOnTask := False;
。
我首先显示一个登录表单,这是一个通过调用
TForm
继承自 LoginForm.ShowModal()
的自定义表单。项目的 Windows 任务栏图标出现,预览显示登录表单。输入信息后预览会保持更新。输入信息后,我将继续显示另一个自定义“TForm”,同时在后台创建内容。这也反映在 Windows 任务栏预览中。创建完成后,我将显示主视图。任务栏现在将登录表单显示为任务栏预览,即使它不再出现在屏幕上的任何位置。然后,我通过调用下面两个函数之一来显示其他弹出自定义表单,具体取决于我是否希望它是模态的。
// Set form to stay on top
SetWindowPos(Self.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOSENDCHANGING);
Self.Show();
// Set form to stay on top
SetWindowPos(Self.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOSENDCHANGING);
Result := Self.ShowModal();
Application.MainFormOnTask := True;
时情况略有不同。我显示的登录和创建表单与以前相同。但是,直到显示 MainView 后,任务栏图标才会出现。在整个运行过程中,预览都会保持更新。但是,当显示模态形式时,使用上述方法,z 顺序将位于非模态形式的后面。
希望这对某人有帮助,我发现让模态表单出现在
StayOnTop
表单上方的唯一可靠方法是在调用 PopupMode
之前立即设置 ShowModal
。
您可以通过创建一个新的 Delphi 11 应用程序轻松重现模态表单出现在
StayOnTop
表单后面的问题,该应用程序具有两个表单:Form1 (FormStyle := fsStayOnTop;
) 和包含 TComboBox
和公共方法 SetEnvironment
的 Form2 .
Form2
SetEnvironment
只是清除 TComboBox.Items
:
procedure TForm2.SetEnvironment;
begin
// Comment out the below line and it doesn't matter where PopupMode is set
// it always works as expected
ComboBox1.Items.Clear;
end;
Form1 有
FormStyle := fsStayOnTop
并有一个以模态方式显示 Form2 的按钮:
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2 := TForm2.Create(nil);
// Form2.PopupMode := pmAuto; {---> Uncomment this line and Form2 will appear BEHIND Form1}
Form2.SetEnvironment;
// Form2.PopupMode := pmAuto; {---> Uncomment this line and Form2 will appear IN FRONT of Form1}
Form2.ShowModal;
Form2.Free;
end;
如果在Form2中注释掉
ComboBox1.Items.Clear
,那么设置PopupMode
的顺序并不重要,Form2总是显示在Form1之上。