调用TsaveDialog时,我的详细信息表单隐藏在主表单后面 [英] My detail form is hidden behind main form when calling the TsaveDialog

查看:75
本文介绍了调用TsaveDialog时,我的详细信息表单隐藏在主表单后面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序基于MainForm,DetailForms和DialogForms。
在任务栏上,我可以看到MainFormButton以及DetailForms。
因此,我使用:

My application is based of a MainForm, DetailForms and DialogForms. On the taskbar I can see the MainFormButton and also the DetailForms. Therefore I use:

procedure <DetailForm>.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  Params.WndParent:= GetDesktopWindow;  
end; 

我使用的是delphi 2010,并且设置了Application.MainFormOnTaskbar:= True;
当我在Detailform中使用PromptForFileName或TSaveDialog时,DetailForm进入Mainform的后面。
关闭对话框后,DetailForm返回。

I use delphi 2010 and I've set Application.MainFormOnTaskbar:= True; When I use PromptForFileName or TSaveDialog in the Detailform then the DetailForm go behind the Mainform. The DetailForm come back after closing the dialog.

当我使用DialogForm(TForm的Showmodal具有属性PopupMode:pmAuto)时,我的DetailForm停留在主窗体之间和对话框。
如何强制将TSaveDialog像具有属性PopupMode:pmAuto的showmodal一样,或如何防止我的detailform落后于主窗体

When I use DialogForm (Showmodal of TForm with property PopupMode: pmAuto) then my DetailForm is stay between the main and dialog. How can I force the TSaveDialog like a showmodal with property PopupMode: pmAuto or how can i prevent that my detailform goes behind the mainform

Demo:

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

  {$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.







unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  oForm: TForm;
begin
  oForm:= Unit2.TForm2.Create(Self);
  oForm.Show;
end;
end.







unit Unit2;

interface

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

type
  TForm2 = class(TForm)

    SaveDialog1: TSaveDialog;
    procedure cxButton1Click(Sender: TObject);
  private
  protected
    procedure CreateParams(var Params: TCreateParams); override;
        { Private declarations }

  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TForm2 }

procedure TForm2.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  Params.WndParent:= 0;   // --> Testing
end;

procedure TForm2.cxButton1Click(Sender: TObject);
begin
  self.SaveDialog1.execute();
end;

end.


推荐答案

步骤1是您不得创建桌面窗口表单的所有者。 Raymond Chen 解释为什么没有。

Step 1 is that you must not make the desktop window the owner of your form. Raymond Chen explains why not.

要真正了解正在发生的事情,您需要阅读窗口功能,以更清晰地了解窗口所有权。并且要非常小心,窗口所有权是一个与Delphi组件所有权完全无关的概念。用Delphi的术语来说,窗口所有权是由 PopupParent 属性控制的。

To really understand what's happening you need to read Window Features on MSDN to get a clearer understanding of window ownership. And be very careful that window ownership is a concept completely unrelated to Delphi component ownership. In Delphi terms, window ownership is controlled by the PopupParent property.

正如注释中所阐明的,您想要两种形式都是无主的,顶层窗口。主要形式是自动的。对于详细信息表单,您需要将 WndParent 设置为 0 就是这样:

As has been clarified in comments, you want both forms to be unowned, top-level windows. The main form automatically is that. For the details form you need to set WndParent to 0 and that's it:

procedure <DetailForm>.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := 0;
end; 

最后一步是确保保存对话框正确拥有。为此,请在调用 Execute 时指定所有者:

The final step is to make sure that the save dialog is owned properly. To do that specify the owner when you call Execute:

Self.SaveDialog1.Execute(Self.Handle);

因此,总的来说,您需要进行三处更改:

So, in summary you need to make three changes:


  1. 将详细信息表单的 WndParent 设置为 0

  2. 删除 WS_EX_APPWINDOW 扩展样式,无名的顶级窗口不需要此样式。

  3. 传递在保存对话框中调用 Execute 时,详细信息表单的句柄。

  1. Set the detail form's WndParent to 0.
  2. Remove the WS_EX_APPWINDOW extended style, it is not needed for an unowned top-level window.
  3. Pass the detail form's handle when calling Execute on the save dialog.






更新

事实证明您正在使用XP,并且显示文件对话框的Delphi代码是垃圾。尽管您将句柄传递给 Execute 方法,该方法将被忽略,并且主窗口句柄将用作对话框的所有者。这就是主窗口位于最前面的原因。

It turns out that you are using XP, and the Delphi code that shows the file dialog is rubbish. Although you pass a handle to the Execute method, that is ignored and the main window handle is used as the dialog's owner. And that's why the main window comes to the front.

您可以通过将 Application.ModalPopupMode 设置为 pmAuto 。您可能应该在.dpr文件中进行设置。

You can get around this by setting Application.ModalPopupMode to pmAuto. You should probably set this in your .dpr file.

在此处了解更多信息: http://blogs.embarcadero.com/abauer/2005/09/30/21517

Read more about this here: http://blogs.embarcadero.com/abauer/2005/09/30/21517

这篇关于调用TsaveDialog时,我的详细信息表单隐藏在主表单后面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆