从IfileOperation.GetDisplayName中的IShellItem获取文件名

从IfileOperation.GetDisplayName中的IShellItem获取文件名,shell,delphi,com,shfileoperation,Shell,Delphi,Com,Shfileoperation,我钩住了IFileOperation的CopyItems方法来监视/拦截windows中的文件复制。 我的问题是如何从IShellItem(CopyItems的最后一个参数)检索完整文件名 psiDestinationFolder有一个名为GetDisplayName的方法,该方法只返回开始复制的当前文件的文件夹名!!但我想得到完整的文件名,却不知道该怎么办!?有没有其他方法可以帮助我获得全名??或者我必须使用另一个API 如果我的英语不好,请原谅 CopyItems方法可能复制多个项目。因此,

我钩住了
IFileOperation
CopyItems
方法来监视/拦截windows中的文件复制。 我的问题是如何从
IShellItem
(CopyItems的最后一个参数)检索完整文件名

psiDestinationFolder
有一个名为
GetDisplayName
的方法,该方法只返回开始复制的当前文件的文件夹名!!但我想得到完整的文件名,却不知道该怎么办!?有没有其他方法可以帮助我获得全名??或者我必须使用另一个API


如果我的英语不好,请原谅

CopyItems方法可能复制多个项目。因此,一下子你就错找了一个文件名。这是一个非常复杂的API,您需要仔细阅读并清楚地理解函数的工作原理

psiDestinationFolder
参数是标识目标的
IShellItem
。使用
GetDisplayName
方法获取文件路径

另一个参数,
punkItems
更复杂。记录如下:

指向IShellItemArray、IDataObject或IEnumShellItems对象的IUnknown的指针,该对象表示要复制的项组。您还可以指向IPersistIDList对象来表示单个项,从而有效地实现与IFileOperation::CopyItem相同的功能

这告诉您,在您收到的
IUnknown
接口后面可能有
IShellItemArray
IDataObject
IEnumShellItems
IPersistIDList
对象。单个对象中可能有多个项目,每个项目都要复制到目标文件夹。您需要依次查询每个可能的接口的
punkItems
,直到您找到必须处理的这些可能性。然后用特殊代码处理每一个。为了测试这一点,您需要编写代码,用每个可能的接口调用
CopyItems
。您将从四个接口中的每个接口的文档中了解如何完成所有这些。如果您还不熟悉shell编程和COM,请在完成这项工作时完成


最后,我怀疑这是检测文件复制的一种非常好的方法。使用许多不同的API复制文件。而
IFileOperation.CopyItems
只是其中之一。如果你只钩住IFileOperation.CopyItems,那么你会错过很多文件复制操作。

这不是TCustomFileDialog.GetItemName所做的吗?@TLama我使用这个方法,但只返回文件路径!而不是完整的文件名!在两种情况下,我得到了相同的结果。Davide,punkItems可以帮助我获得源文件的文件路径!为此,我应该使用
punkItems.QueryInterface(IID\u IShellItemArray,\u ShellItemArray)
将punkItems转换为
ShellItemArray
,然后从
ShellItemArray
获取当前文件路径!但是
QueryInterface
总是返回false!你能帮我转换吗?请再次阅读我的答案和文档。仔细阅读并理解punkItems可能是不支持IShellItemArray的对象。我阅读了您的答案,我测试了转换为
IDataObject
,但只返回false
punkItems.QueryInterface(IID\u IDataObject,\u DataObject)
!继续浏览列表。不过,我的最后一段给出了最好的建议。谢谢,关于你的最后一段:我发现挂钩
ZwReadFile
ZwWriteFile
是最好的方法!它工作得很好,但很难将FileCopy/FileCut与其他文件操作区分开来!
function New_CopyItems(p: Pointer; punkItems: IUnknown;psiDestinationFolder: IShellItem): HResult; stdcall;