How to bring an OpenDialog hidden by another window to the front

2.4k views Asked by At

I have an application with multiple forms and a separate taskbar button for each form.

Let's say form2 displays an OpenDialog, I click away to another maximized application covering the full screen area, then I go back to form2 by selecting it's taskbar button. Voila! The OpenDialog is hidden behind the other application I selected, and I have to click on the now non-accessible form2 to bring the dialog back to the front. This is really annoying and may confuse the user.

Here is some code to illustrate the issue:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Unit2;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show;
end;

end.
________________

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
  OpenDialog1.Execute;
end;

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

end.

Is it possible maybe to get the handle of the visible opendialog? It used to be possible, but with the new Vista style OpenDialog if I trap OnDialogShow the OpenDialog reverts back to the old style which is a no go for me now.

Any ideas?

2

There are 2 answers

6
Remy Lebeau On

TOpenDialog.Execute() has an optional parameter that lets you specify a parent window that the dialog is not allowed to fall behind:

procedure TForm2.Button1Click(Sender: TObject);
begin
  OpenDialog1.Execute(Self.Handle);
end;

If you do not specify a parent window, the active Form's window is used if Application.ModalPopupMode is not pmNone, otherwise the Application.MainForm window is used instead.

1
Steve On

So I've figured out how to bring the dialog to the front, but there is still one problem: the focus is on Form2, not the dialog. If someone can tell me how to put the focus on the opendialog instead of Form2 and post it as an answer, I'll accept it.

Here are the code excerpts to add to the original:

type
  TForm1 = class(TForm)
  private
      procedure WMActivate(var Msg: TWMActivate); message WM_ACTIVATE;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  DialogFormHandle: HWnd;

...

procedure TForm1.WMActivate(var Msg: TWMActivate);
begin
    inherited;

    if DialogFormHandle <> 0 then
    begin
      BringWindowToTop(DialogFormHandle);
      exit;
    end;
end;

...

procedure TForm2.Button1Click(Sender: TObject);
begin
  try
    DialogFormHandle := Handle;
    OpenDialog1.Execute(Handle);
  finally
    DialogFormHandle := 0;
  end;
end;

Thanks!