I have a form that calls TOpenDialog. When the window comes up I right clicked one of the displayed files and clicked properties. After closing the Windows properties window the open dialog window falls to the bottom of the Z-Order behind the calling form and main application. Using alt+tab (as I have read in similar posts here) will bring the open dialog window to the front, but i'd like a better solution. Most of the research I've done seems to apply only to the TForm class. Is there a way to better control the Z-Order of TOpenDialog? I am using Delphi 2006. I have similar code in a Delphi 2007 application and this problem doesn't occur (if that helps any). Thanks in advance.
-
In my experience, the VCL code of that era was basically rubbish at handling window ownership. That's the key point. An owned window is always on top of its owner. Personally I use my own wrappers to the underlying APIs so that I can do it right. – David Heffernan Jul 09 '14 at 19:30
-
@David Heffernan: I actually have only heard of wrappers. I will admit that I don't know what they are exactly. I'll look into it for the future. Thanks for commenting. – CodeMonkey Jul 09 '14 at 19:43
-
TOpenDialog is a wrapper. – David Heffernan Jul 09 '14 at 19:44
1 Answers
In Delphi 2006 and later, TOpenDialog.Execute()
has an optional ParentWnd
parameter. When not specified, Execute()
does some hunting to decide which parent window to use for z-order purposes:
If
Application.ModalPopupMode
is notpmNone
,Application.ActiveFormHandle
is used.If
Application.ModalPopupMode
ispmNone
, orApplication.ActiveFormHandle
is 0,Application.Handle
is used instead. In Delphi 2007 and later, with the introduction of theTApplication.MainFormOnTaskbar
property, ifMainFormOnTaskbar
is true andApplication.MainForm
is assigned,Application.MainFormHandle
is used instead ofApplication.Handle
.Application.MainFormHandle
triggers theTApplication.OnGetMainFormHandle
event if assigned. If not assigned, or if it returns 0,Application.MainForm.Handle
is used.
In Delphi versions up to, and including, 2006, TOpenDialog
always uses the legacy Win32 API GetOpenFileName()
function. In Delphi 2007 and later, TOpenDialog
uses the newer IFileOpenDialog
API if all of the following criteria are met, otherwise it falls back to GetOpenFileName()
:
the app is running on Vista or later.
the
Dialogs.UseLatestCommonDialogs
global variable is true.the
TOpenDialog.Template
property is nil.no
OnIncludeItem
,OnClose
, orOnShow
event handler is assigned toTOpenDialog
.
When TOpenDialog
uses IFileOpenDialog
, Execute()
respects the specified parent window.
When TOpenDialog
uses GetOpenFileName()
, Execute()
IGNORES the specified parent window if Application.ModalPopupMode
is pmNone
and uses Application.MainFormHandle
/Application.Handle
instead!
So, to solve your problem in all Delphi versions from 2006 onwards, pass your form's Handle
to the ParentWnd
parameter, and set Application.ModalPopupMode
to a value other than pmNone
, then the dialog will use your form's window as its parent and thus can never appear behind it. Don't let the VCL decide which parent window to use.
BTW, everything I have said applies to TSaveDialog
as well.

- 555,201
- 31
- 458
- 770
-
I am passing Self.Handle as the parameter when calling TOpenDialog.Execute. It still is doing it. Maybe I am missing something. – CodeMonkey Jul 09 '14 at 19:16
-
@CodeMonkey: Did you miss the rest of that paragraph about setting `Application.ModalPopupMode` as well? – Ken White Jul 09 '14 at 19:32
-
@Ken White: Yes I read right over it because I was trying to multitask. I apologize. I tried the solution with setting ModalPopupMode to pmExplicit as its explanation seemed to be the most appropriate and It seems to be working. Thank you both. – CodeMonkey Jul 09 '14 at 19:40