Delphi OpenDialog without letting the user navigate away from the inital dir
-
02-10-2019 - |
Question
I am trying to create an open dialog (in Windows 7) where the user is confined to the initial directory. On the open dialog I have set the optionsEX to [ofExNoPlacesBar] and that removes the bar that would let them select folders and directories to go to quickly but the user can use the bread crumb address tool to go up a level and type a different directory into the filename text box to change directories.
Thank you
Solution
If you are using Delphi 2009+, there is a TFileOpenDialog
. Use this, and set
procedure TForm3.FileOpenDialog1FolderChange(Sender: TObject);
begin
FInitiated := true;
end;
procedure TForm3.FileOpenDialog1FolderChanging(Sender: TObject;
var CanChange: Boolean);
begin
CanChange := not FInitiated;
end;
procedure TForm3.btnOpenClick(Sender: TObject);
begin
FInitiated := false;
FileOpenDialog1.DefaultFolder := 'C:\MyFolder\';
FileOpenDialog1.Execute;
end;
where
var
FInitiated: boolean;
(Notice that there should be exactly one FInitiated
per TFileOpenDialog
. So, if FileOpenDialog
is a private member of TForm3
, let FInitiated
be a private member of TForm3
as well.)
To improve the user experience, you will probably use
procedure TForm3.FileOpenDialog1FolderChanging(Sender: TObject;
var CanChange: Boolean);
begin
CanChange := not FInitiated;
if not CanChange then beep;
end;
or
procedure TForm3.FileOpenDialog1FolderChanging(Sender: TObject;
var CanChange: Boolean);
begin
CanChange := not FInitiated;
if not CanChange then
MessageBox(Handle, PChar('Directory selection is not allowed.'), PChar(Caption), MB_ICONINFORMATION);
end;
OTHER TIPS
Use a different open dialog (make a form yourself with no folder navigation, only a file list box), or simply audit for a path not matching the initial dir and refuse to actually open the file.
The 'FileOpenDialog' has an OnFolderChanging
event of type TFileDialogFolderChangingEvent
which have a boolean CanChange
parameter. I'd expect setting this parameter to false would serve the purpose.
edit:
Example usage as per Remy's comments (if I understood correctly);
procedure TForm1.FileOpenDialog1FolderChanging(Sender: TObject;
var CanChange: Boolean);
var
Dlg: TFileOpenDialog;
DefFolder: IShellItem;
iOrder: Integer;
begin
CanChange := False;
Dlg := Sender as TFileOpenDialog;
if Succeeded(SHCreateItemFromParsingName(PWideChar(WideString(Dlg.DefaultFolder)), nil, IShellItem, DefFolder)) then
try
CanChange := Dlg.ShellItem.Compare(DefFolder, SICHINT_ALLFIELDS, iOrder) = S_OK;
finally
DefFolder := nil;
end;
end;
The below also works but more vulnerable to path variations (see Andreas' comments below);
procedure TForm1.FileOpenDialog1FolderChanging(Sender: TObject;
var CanChange: Boolean);
begin
CanChange := SameFileName(TFileOpenDialog(Sender).FileName,
TFileOpenDialog(Sender).DefaultFolder);
end;