从 Delphi 中的 OpenDialog 选择中获取特殊文件夹路径
Getting Special Folder Path from OpenDialog selection in Delphi
我通过 OpenDialog 组件让我的用户 select 一个文件夹。
但是,当他们 select 文件夹(例如“文档”或“我的视频”或类似的东西)时,路径只是文件夹的名称。
我可以通过API获取此类文件夹的路径,但我如何获取路径
基于他们在 OpenDialog 中 select编辑的内容?
我相信您实际上是在谈论用户 select 使用 Windows 7 库。在这种情况下,您需要使用特殊代码来查找该库的默认保存位置。
您需要使用 IFileDialog
界面来执行此操作。如果您使用 TOpenDialog
则您无权访问 IFileDialog
界面。因此,您需要使用 Vista 对话框 TFileOpenDialog
,它会公开 IFileDialog
界面。
一旦你有了这个接口,你就可以为每个 selected shell 项目获得 IShellItem
接口,通过调用 GetResults
多 select 对话框, GetResult
用于单个 select 对话框。然后,您可以将这些 IShellItem
接口传递给这样的函数:
function ShellItemFileSystemPath(const si: IShellItem): string;
var
attribs: DWORD;
pszPath: PChar;
lib: IShellLibrary;
defSaveFolder: IShellItem;
begin
OleCheck(si.GetAttributes(SFGAO_FILESYSTEM, attribs));
if attribs=0 then begin
// This could be a library, in which case we shall return the default save location
if Succeeded(CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER, IID_IShellLibrary, lib))
and Succeeded(lib.LoadLibraryFromItem(si, STGM_READ))
and Succeeded(lib.GetDefaultSaveFolder(DSFT_DETECT, IShellItem, defSaveFolder)) then begin
Result := ShellItemFileSystemPath(defSaveFolder);
exit;
end;
raise EValidityError.CreateFmt(
'Cannot operate on ''%s'' because it is not part of the file system.',
[ShellItemDisplayName(si)]
);
end;
OleCheck(si.GetDisplayName(SIGDN_FILESYSPATH, pszPath));
Try
Result := pszPath;
Finally
CoTaskMemFree(pszPath);
End;
end;
Embarcadero 库中的代码应该是这样做的,但遗憾的是该库代码有缺陷。它现在应该支持 Windows 7 个库。
就个人而言,由于这个问题和其他问题,我不使用 Embarcadero 提供的文件对话框。
我通过 OpenDialog 组件让我的用户 select 一个文件夹。
但是,当他们 select 文件夹(例如“文档”或“我的视频”或类似的东西)时,路径只是文件夹的名称。
我可以通过API获取此类文件夹的路径,但我如何获取路径 基于他们在 OpenDialog 中 select编辑的内容?
我相信您实际上是在谈论用户 select 使用 Windows 7 库。在这种情况下,您需要使用特殊代码来查找该库的默认保存位置。
您需要使用 IFileDialog
界面来执行此操作。如果您使用 TOpenDialog
则您无权访问 IFileDialog
界面。因此,您需要使用 Vista 对话框 TFileOpenDialog
,它会公开 IFileDialog
界面。
一旦你有了这个接口,你就可以为每个 selected shell 项目获得 IShellItem
接口,通过调用 GetResults
多 select 对话框, GetResult
用于单个 select 对话框。然后,您可以将这些 IShellItem
接口传递给这样的函数:
function ShellItemFileSystemPath(const si: IShellItem): string;
var
attribs: DWORD;
pszPath: PChar;
lib: IShellLibrary;
defSaveFolder: IShellItem;
begin
OleCheck(si.GetAttributes(SFGAO_FILESYSTEM, attribs));
if attribs=0 then begin
// This could be a library, in which case we shall return the default save location
if Succeeded(CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER, IID_IShellLibrary, lib))
and Succeeded(lib.LoadLibraryFromItem(si, STGM_READ))
and Succeeded(lib.GetDefaultSaveFolder(DSFT_DETECT, IShellItem, defSaveFolder)) then begin
Result := ShellItemFileSystemPath(defSaveFolder);
exit;
end;
raise EValidityError.CreateFmt(
'Cannot operate on ''%s'' because it is not part of the file system.',
[ShellItemDisplayName(si)]
);
end;
OleCheck(si.GetDisplayName(SIGDN_FILESYSPATH, pszPath));
Try
Result := pszPath;
Finally
CoTaskMemFree(pszPath);
End;
end;
Embarcadero 库中的代码应该是这样做的,但遗憾的是该库代码有缺陷。它现在应该支持 Windows 7 个库。
就个人而言,由于这个问题和其他问题,我不使用 Embarcadero 提供的文件对话框。