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;
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.
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.
Step 1 is that you must not make the desktop window the owner of your form. Raymond Chen explains why not.
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.
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;
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:
WndParent
to 0
.WS_EX_APPWINDOW
extended style, it is not needed for an unowned top-level window.Execute
on the save dialog.Update
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.
You can get around this by setting Application.ModalPopupMode
to pmAuto
. You should probably set this in your .dpr file.
Read more about this here: http://blogs.embarcadero.com/abauer/2005/09/30/21517
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With