Workaround
Use a TFileOpenDialog
instead*.
Set FileOpenDialog1.Options:= [fdoPickFolders,fdoPathMustExist]

Now you have a dialog that:
- Always works.
- Allows copy paste
*) Not to be confused with the TOpenDialog, which does not allow you to only select folders.
Solution for Windows XP
Note that the new TFileOpenDialog only works for Vista and above.
Your program will not work on XP if you include this control.
If you start the dialog on XP it will generate an EPlatformVersionException
.
You may want to use the following code instead if you want to be backward compatible:
uses JclSysInfo; //because you have XE use JCL.
...
var
WinMajorVer: Integer;
Directory: string;
FileDialog: TFileOpenDialog;
begin
WinMajorVer:= GetWindowsMajorVersionNumber;
if WinMajorVer < 6 then begin //pre-vista
//To show the root Desktop namespace, you should be setting the Root parameter to an empty string ('') instead of 'Desktop'
FileCtrl.SelectDirectory('Caption', '', Directory, [sdNewUI, sdShowEdit]);
end else begin
FileDialog:= TFileOpenDialog.Create(self);
try
FileDialog.Options:= [fdoPickFolders,fdoPathMustExist];
if FileDialog.Execute then Directory:= FileOpenDialog1.FileName;
finally
FileDialog.Free;
end;
end;
Result:= Directory;
end;
Recommended reading:
detect windows version
EDIT
FileCtrl.SelectDirectory('Caption', 'Desktop', Directory, [sdNewUI, sdShowEdit]);
The 'Desktop'
goes into the Root
parameter, which is handled like so:
...
SHGetDesktopFolder(IDesktopFolder);
IDesktopFolder.ParseDisplayName(Application.Handle, nil,
Root, Eaten, RootItemIDList, Flags);
...
Here's what MSDN for IDesktopFolder.ParseDisplayName has to say:
pszDisplayName [in]
Type: LPWSTR
A null-terminated Unicode string with the display name. Because each Shell folder defines its own parsing syntax, the form this string can take may vary. The desktop folder, for instance, accepts paths such as "C:\My Docs\My File.txt". It also will accept references to items in the namespace that have a GUID associated with them using the "::{GUID}" syntax.
Note that the documentation states that the desktop folder will accept paths and guids. It does not accept 'Desktop'
. Because that's neither.
The fact that 'Desktop'
as a root
works on one system but not another is some undocumented fix made in an older/newer version of the IDesktopFolder
interface.
Technical solution
Use ''
as a 'root' as shown in my code above.
Obviously SelectDirectory
is a really bad design by Microsoft that should never be used. It just sucks in so many ways. I recommend it not be used whenever possible.