1

[编辑]

function PathFromShellItem(AShellItem: IShellItem): string;
{Helper function to get path from ShellItem}
var
  hr: HRESULT;
  iPath: PWideChar;
begin
  hr := AShellItem.GetDisplayName(SIGDN_FILESYSPATH, iPath);
  if hr = 0 then
    Result := iPath
  else
    Result := '';
end;

下面的代码尝试从 IShellItem 获取文件夹名和文件名。文件名 (iName) 获取正确,但文件夹名称 (iFolder) 始终为“”。为什么 pfd.GetFolder 不返回文件夹名称?我是否试图以错误的方式获取文件夹名称?

function TFileDialogEvent.OnSelectionChange(const pfd: IFileDialog): HResult; stdcall;
{Handle the OnSelectionChange event and fill labels with information}
var
  ShellItem: IShellItem;
  iFilename: string;
  iFolder: string;
  iName: PWideChar;
begin
  if pfd.GetFolder(ShellItem) = S_OK then
    iFolder := PathFromShellItem(ShellItem);
  OleCheck(pfd.GetFileName(iName));
  {Set the filepath}
  if DirectoryExists(iFolder) then
    iFilename := IncludeTrailingPathDelimiter(iFolder) + string(iName);
end;
4

1 回答 1

2

您的代码PathFromShellItem不正确。你想要这样的东西,灵感来自文件对话框的 VCL 代码:

function GetItemName(const Item: IShellItem; var ItemName: string): HRESULT;
var
  pszItemName: PWideChar;
begin
  Result := Item.GetDisplayName(SIGDN_FILESYSPATH, pszItemName);
  if Failed(Result) then
    Result := Item.GetDisplayName(SIGDN_NORMALDISPLAY, pszItemName);
  if Succeeded(Result) then
  try
    ItemName := pszItemName;
  finally
    CoTaskMemFree(pszItemName);
  end;
end;

function FileDialogFilename(const pfd: IFileDialog): string;
var
  Item: IShellItem;
  FileName: string;
  pszFileName: PWideChar;
begin
  if Succeeded(pfd.GetFolder(Item)) and 
     Succeeded(GetItemName(Item, FileName)) and
     Succeeded(pfd.GetFileName(pszFileName)) then
  try
    Result := TPath.Combine(FileName, pszFileName);
  finally
    CoTaskMemFree(pszFileName);
  end;
end;

TCustomFileDialog.GetFileName如果您不能实际使用TFileOpenDialog自己,则可以将其用作此代码的模板。想一想,为什么不能直接使用TFileOpenDialog.

于 2013-03-03T21:25:26.047 回答