如何在其所有者表单之上显示模态表单(其所有者是否设置为 fsStayOnTop),就像 TOpenDialog 一样

发布于 2024-10-25 06:08:46 字数 4987 浏览 9 评论 0原文

总结:

请参阅下面 Craig 和 Sertac 提供的有用评论。

=================================================== ====

如下面的最小化代码所示,TForm10 设置为 fsStayOnTopTForm10.btnTryDlgClick 调用 dlgOpen1.Execute,显示的对话框符合预期。但是,当我在 TForm10.btnTryFormClick 内调用 TForm11.Create(Self).ShowModal 时,表单隐藏在 TForm10 后面。我想知道如何理解这种行为,以及为什么标准 TOpenDialog 可以按预期显示?任何评论表示赞赏!

PS:一种解决方法是重写 TForm11 的 CreateParams 过程,并将 Params.wndParent 设置为 0。但在我看来,使用此解决方法会破坏窗口层次结构。

  procedure TForm11.CreateParams(var Params: TCreateParams); // override;
  begin
    inherited;
    params.wndParent := 0;
  end;

PS:Remy 在下面的相关 SO 页面中提到了另一个解决方法:将模态表单的 PopupParent 属性设置为 StayOnTop Form。但在随后的评论中,Sertac 提到这种解决方法也会破坏窗口层次结构。

PS:可能相关的SO页面:
fsStayOnTop 表单隐藏的模态表单
如何防止 FindDialog 停留在顶部(德尔福)?
如何确保对话框始终位于主窗口的前面
调用 ShowModal 时,表单隐藏在其他表单后面
使 2 个表单能够相互重叠?
多表单 Delphi 应用程序和对话框
新创建的模态窗口失去焦点并变成在 Windows Vista 中无法访问
Delphi - 如何防止 Forms/MsgBox 移动根据先前的表格?
如何允许Delphi辅助表单位于主表单后面
使用 Show 的假模态对话框?
Delphi MainFormOnTaskBar 模态窗口 bug

第 10 单元的源代码:

    unit Unit10;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;

    type
      TForm10 = class(TForm)
        btnTryDlg: TButton;
        dlgOpen1: TOpenDialog;
        btnTryForm: TButton;
        procedure FormCreate(Sender: TObject);
        procedure btnTryDlgClick(Sender: TObject);
        procedure btnTryFormClick(Sender: TObject);
      end;

    var
      Form10: TForm10;

    implementation

    {$R *.dfm}

    uses
      Unit11;

    procedure TForm10.FormCreate(Sender: TObject);
    begin
      FormStyle := fsStayOnTop;
    end;

    procedure TForm10.btnTryDlgClick(Sender: TObject);
    begin
      dlgOpen1.Execute;
    //  dlgOpen1.Execute(Self.Handle);
    end;

    procedure TForm10.btnTryFormClick(Sender: TObject);
    begin
      TForm11.Create(Self).ShowModal;
    end;

    end.

DFM 第 10

    object Form10: TForm10
      Left = 0
      Top = 0
      Caption = 'Form10'
      ClientHeight = 255
      ClientWidth = 414
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      OnCreate = FormCreate
      PixelsPerInch = 96
      TextHeight = 13
      object btnTryDlg: TButton
        Left = 32
        Top = 24
        Width = 153
        Height = 201
        Caption = 'Try dialog'
        TabOrder = 0
        OnClick = btnTryDlgClick
      end
      object btnTryForm: TButton
        Left = 224
        Top = 24
        Width = 153
        Height = 201
        Caption = 'btnTryForm'
        TabOrder = 1
        OnClick = btnTryFormClick
      end
      object dlgOpen1: TOpenDialog
        Left = 96
        Top = 168
      end
    end

单元的源代码:

    unit Unit11;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

    type
      TForm11 = class(TForm)
      end;


    implementation

    {$R *.dfm}

    end.

DFM对于第 11 单元:

    object Form11: TForm11
      Left = 0
      Top = 0
      Caption = 'Form11'
      ClientHeight = 183
      ClientWidth = 203
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
    end

Summarization:

Please see the helpful comments below from Craig and Sertac.

======================================================

As shown in the following minimized code, TForm10 is set to be fsStayOnTop. TForm10.btnTryDlgClick call dlgOpen1.Execute, and the dialog shown is as expected. However, when I call TForm11.Create(Self).ShowModal inside TForm10.btnTryFormClick, the form is hidden behind the TForm10. I am wondering how to understand this behavior, and why standard TOpenDialog can show as expected? Any comment is appreciated!

PS: One workaround is to override the CreateParams procedure of TForm11, and set Params.wndParent to 0. But it looks to me that window hierarchy will be broke using this workaround.

  procedure TForm11.CreateParams(var Params: TCreateParams); // override;
  begin
    inherited;
    params.wndParent := 0;
  end;

PS: Another workaround is mentioned by Remy in the below relevant SO pages: setting the modal Form's PopupParent property to be the StayOnTop Form. But in the followed comments, Sertac mentioned this workaround will also break window hierarchy.

PS: Possibly relevant SO pages:
Modal forms hidden by fsStayOnTop forms
How Can I Keep the FindDialog from Staying on Top (Delphi)?
How to make sure a dialog is always front of the main window
Form is hidden behind other forms when ShowModal is called
Make 2 forms able to overlap each other?
Multiple form Delphi applications and dialogs
Newly created modal window loses focus and become inacessible in Windows Vista
Delphi - How to prevent Forms/MsgBoxes to move under prior form?
How to allow Delphi secondary forms behind the main form
Fake modal dialog using Show?
Delphi MainFormOnTaskBar Modal windows bug

Source for Unit10:

    unit Unit10;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;

    type
      TForm10 = class(TForm)
        btnTryDlg: TButton;
        dlgOpen1: TOpenDialog;
        btnTryForm: TButton;
        procedure FormCreate(Sender: TObject);
        procedure btnTryDlgClick(Sender: TObject);
        procedure btnTryFormClick(Sender: TObject);
      end;

    var
      Form10: TForm10;

    implementation

    {$R *.dfm}

    uses
      Unit11;

    procedure TForm10.FormCreate(Sender: TObject);
    begin
      FormStyle := fsStayOnTop;
    end;

    procedure TForm10.btnTryDlgClick(Sender: TObject);
    begin
      dlgOpen1.Execute;
    //  dlgOpen1.Execute(Self.Handle);
    end;

    procedure TForm10.btnTryFormClick(Sender: TObject);
    begin
      TForm11.Create(Self).ShowModal;
    end;

    end.

DFM for Unit10:

    object Form10: TForm10
      Left = 0
      Top = 0
      Caption = 'Form10'
      ClientHeight = 255
      ClientWidth = 414
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      OnCreate = FormCreate
      PixelsPerInch = 96
      TextHeight = 13
      object btnTryDlg: TButton
        Left = 32
        Top = 24
        Width = 153
        Height = 201
        Caption = 'Try dialog'
        TabOrder = 0
        OnClick = btnTryDlgClick
      end
      object btnTryForm: TButton
        Left = 224
        Top = 24
        Width = 153
        Height = 201
        Caption = 'btnTryForm'
        TabOrder = 1
        OnClick = btnTryFormClick
      end
      object dlgOpen1: TOpenDialog
        Left = 96
        Top = 168
      end
    end

Source for Unit11:

    unit Unit11;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

    type
      TForm11 = class(TForm)
      end;


    implementation

    {$R *.dfm}

    end.

DFM for Unit11:

    object Form11: TForm11
      Left = 0
      Top = 0
      Caption = 'Form11'
      ClientHeight = 183
      ClientWidth = 203
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
    end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

亽野灬性zι浪 2024-11-01 06:08:46

设置模态表单的 PopupParent 属性,就像 Remy 建议的那样。这将使对话框成为 StayOnTop 表单的父级,这就是对话框的 Execute 方法已经执行的操作。我不确定 Sertac 的注释来自哪里,但使用 PopupParent 可以正确设置窗口层次结构,因此对话框将始终位于 StayOnTop 表单上方。

Set the modal form's PopupParent property, exactly like Remy suggested. That will parent the dialog to the StayOnTop form, which is what the dialog's Execute method is already doing. I'm not sure where Sertac's comments are coming from, but using PopupParent sets the window heirarchy correctly, so the dialog will always be above the StayOnTop form.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文