确定文件是否位于Delphi 2007中ItemIDList的虚拟位置

时间:2014-09-03 17:50:41

标签: windows delphi

我正在使用Angus Johnson& Co.的TDropPIDLTarget组件。 Anders Melander的拖放组件套件允许用户通过将附件拖入表单来添加附件。我遇到的问题是确定文件是来自虚拟位置(即:摄像头驱动器还是iPhone驱动器)还是来自常规文件系统。这是我正在使用的概念验证代码:

procedure TfrmForm.dftFileDropDrop(Sender: TObject; ShiftState: TShiftState;
  Point: TPoint; var Effect: Integer);
Var
  I: Integer;
  pItem: PItemIDList;
  Desktop: IShellFolder;
  FileName: TStrRet;
  Attr: UINT;
begin
  If FAILED(SHGetDesktopFolder(Desktop)) Then
    Exit;

  For I := 1 To dftFileDrop.PidlCount - 1 Do
  Begin
    pItem := dftFileDrop.GetAbsoluteFilePidl(I);

    Attr := SFGAO_FileSystem;
    If Succeeded(Desktop.GetAttributesOf(1, pItem, Attr)) Then
    Begin
      If (Attr Or SFGAO_FILESYSTEM) = Attr Then
        Desktop.GetDisplayNameOf(pItem, SHGDN_NORMAL Or SHGDN_FORPARSING, Filename)
      Else
        Desktop.GetDisplayNameOf(pItem, SHGDN_NORMAL Or SHGDN_FORADDRESSBAR, Filename);
      mResults.Lines.Add(Filename.pOleStr);
    End;
  End;
end;

SFGAO_FileSystem常量应该表示:

  

"指定的文件夹或文件是文件系统的一部分(即,   它们是文件,目录或根目录)。已解析的名称   可以假定这些项是有效的Win32文件系统路径。这些   路径可以是UNC或基于驱动器号。"

这听起来像我想要使用但我似乎无法从GetAttributesOf获得正确的结果。我这样做是正确的吗?

1 个答案:

答案 0 :(得分:2)

您需要使用And运算符,而不是Or运算符:

If (Attr and SFGAO_FILESYSTEM) <> 0 Then

您还需要在访问pOleStr之前检查失败(并且您不应该假设该值总是在pOleStr中,因为它可能并非总是如此)。

完成使用后,您还需要释放STRRET内容。最好的方法是使用StrRetTo...()函数之一,它将为您处理,并为您分析STRRET.uType字段,以便它知道在何处以及如何提取字符串数据。

尝试更像这样的事情:

procedure TfrmForm.dftFileDropDrop(Sender: TObject; ShiftState: TShiftState;
  Point: TPoint; var Effect: Integer);
var
  I: Integer;
  pItem: PItemIDList;
  Desktop: IShellFolder;
  FileName: TStrRet;
  Attr: UINT;
  hr: HRESULT;
  szFileName: array[0..MAX_PATH] of Char;
begin
  If FAILED(SHGetDesktopFolder(Desktop)) Then
    Exit;

  For I := 1 To dftFileDrop.PidlCount - 1 Do
  Begin
    pItem := dftFileDrop.GetAbsoluteFilePidl(I);

    If Succeeded(Desktop.GetAttributesOf(1, pItem, Attr)) Then
    Begin
      If (Attr And SFGAO_FILESYSTEM) <> 0 Then
        hr := Desktop.GetDisplayNameOf(pItem, SHGDN_NORMAL Or SHGDN_FORPARSING, Filename)
      Else
        hr := Desktop.GetDisplayNameOf(pItem, SHGDN_NORMAL Or SHGDN_FORADDRESSBAR, Filename);
      If Succeeded(hr) then
      Begin
        if Succeeded(StrRetToBuf(@Filename, pItem, szFileName, MAX_PATH)) then
          mResults.Lines.Add(szFileName);
      End;
    End;
  End;
End;