【问题标题】:How to show a modal form on top of its owner form (its owner is set to fsStayOnTop or not), just as TOpenDialog does如何在其所有者表单之上显示模式表单(其所有者是否设置为 fsStayOnTop),就像 TOpenDialog 一样
【发布时间】:2011-07-20 17:44:00
【问题描述】:

总结:

请参阅下方来自 Craig 和 Sertac 的有用 cmets。

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

如以下最小化代码所示,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 页面中提到了另一种解决方法:setting the modal Form's PopupParent property to be the StayOnTop Form。但在随后的 cmets 中,Sertac 提到这种变通方法也会破坏窗口层次结构。

PS:可能相关的 SO 页面:
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
@ 987654327@
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

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.

Unit10 的 DFM:

    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

Unit11 的来源:

    unit Unit11;

    interface

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

    type
      TForm11 = class(TForm)
      end;


    implementation

    {$R *.dfm}

    end.

Unit11 的 DFM:

    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

【问题讨论】:

  • Xichen - question you refer 的不同之处在于,模态表单是从fsNormal 表单启动的,而应用程序中还有另一个fsStayOnTop 表单。在那个问题中,如果您将模态表单的 PopupParent 设置为顶层表单,它将显然由顶层表单拥有,但它应该由根据应用程序设计启动它的表单拥有。这就是我所说的打破等级制度的意思。
  • 顺便说一句,我复制粘贴了您的代码,无法复制问题,当我单击 btnTryForm 时,模态表单在 Form10 上方。 +1 链接集合(研究)虽然..
  • @Sertac:非常感谢您抽出宝贵的时间和对window hierarchy 提供帮助的cmets!关于目前的问题,很抱歉无法复制。 “它在我的机器上works...”O_O
  • 我也为研究工作+1。

标签: delphi forms dialog modal-dialog stayontop


【解决方案1】:

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

【讨论】:

  • @Craig:非常感谢您的建议!您的意思是在这种情况下使用 PopupParent 是最佳做法吗?你能帮忙确认一下吗?您能否也帮忙评论一下如何在实践中判断window hierarchy是否正确保存?
  • 如果您希望特定对话框始终显示在特定表单上方,那么可以,设置 PopupParent 属性。这就是它的用途。您通常只需将Application.ModalPopupMode 设置为pmAuto,Delphi 将为您处理一切。设置后,对话框将作为当前活动表单的父级(通常是Application.MainForm),而不是Application.Handle,这样可以防止它卡在主表单后面。不起作用的情况是当您有一个未激活的 fsStayOnTop 表单时,在这种情况下对话框将出现在它的后面。
  • 标准对话框依赖Application.ModalPopupMode 来获取它们的父级。您可以在Dialogs.pas::TCommonDialog.Execute 中查看详细信息。这是一个非常相似的想法。其他对话框的详细信息由Forms.pas::TCustomForm.CreateParams处理。
  • 简短回答:将Application.ModalPopupMode 设置为pmAuto,不用担心。您唯一会看到问题的是您同时打开了一个普通表单和一个留在顶部的表单,并且您在普通对话框具有焦点时打开了一个对话框。如果发生这种情况并且对话框应该出现在 fsStayOnTop 表单的顶部,那么将 PopupParent 设置为 fsStayOnTop 表单。
  • @Craig - 我用一个链接对这个问题发表评论,以防有人想知道 cmets 来自哪里。在您的第一条评论中也是如此,模态表单是从普通表单启动的,而还有另一个留在顶部的表单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-12
  • 2012-12-30
相关资源
最近更新 更多