2014-09-03 40 views
0

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

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得到正确的结果。我以正确的方式做这件事吗?

+0

甚至文件系统的项目可以是虚拟的。 – 2014-09-03 18:02:55

回答

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; 
+0

再次感谢您的帮助!我发现整件事情都没有实际意义,不过因为我可以将GetDisplayNameOf选项更改为“SHGDN_NORMAL或SHGN_FORPARSING或SHGDN_FORADDRESSBAR”,我将显示正确的文件名,而不管它是否位于虚拟位置。我没有意识到我需要释放StrRet对象,所以非常感谢。 – Caynadian 2014-09-03 18:51:37

相关问题