1

我正在尝试实现 IFileOperation 接口,需要帮助理解 IFileOperation::DeleteItems 方法的 punkItems 参数。在文档页面上,punkItems 参数被描述为

指向 IShellItemArray、IDataObject 或 IEnumShellItems 对象的 IUnknown 的指针,该对象表示要复制的项目组。

以下代码显示了我如何使用 SHCreateShellItemArrayFromIDLists() 函数来生成 IShellItemArray:

Files := [A_ScriptDir "\foo1.txt", A_ScriptDir "\foo2.txt"]
IID := "{947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8}"
CLSID := "{3ad05575-8857-4850-9277-11b85bdb8e09}"
FileOperation := ComObjCreate(CLSID, IID)
VTBL := NumGet(FileOperation + 0, 0, "Ptr")
DeleteItems := NumGet(VTBL + 0, 19 * A_PtrSize, "Ptr") ; IFileOperation::DeleteItems
PerformOperations := NumGet(VTBL + 0, 21 * A_PtrSize, "Ptr") ; IFileOperation::PerformOperations

VarSetCapacity(PCIDLIST, A_PtrSize * Files.Count(), 0)
PIDLISTS := []
for Each, File in Files {
   PIDLISTS[Each] := DllCall("Shell32.dll\ILCreateFromPath", "Str", File, "Ptr")
   NumPut(PIDLISTS[Each], PCIDLIST, A_PtrSize * (Each - 1), "Ptr")
}
DllCall("Shell32.dll\SHCreateShellItemArrayFromIDLists", "UInt", Files.Count(), "Ptr", &PCIDLIST, "PtrP", pItems, "Int")
for Each, PIDLIST in PIDLISTS
   DllCall("Shell32.dll\ILFree", "Ptr", PIDLIST)

MsgBox % DllCall(DeleteItems, "Ptr", FileOperation, "Ptr", pItems, "UInt") "`n" ErrorLevel "`n" A_LastError
DllCall(PerformOperations, "Ptr", FileOperation, "Int")
ObjRelease(pItems)

但感觉就像我错过了一些东西,例如参数描述的 IUnknown 部分。上述代码有效,但 A_LastError 产生 ERROR_NO_TOKEN - 尝试引用不存在的令牌 (1008)。您能帮我理解如何获得“指向 IShellItemArray 的 IUnknown 的指针”吗?

谢谢你。

4

1 回答 1

1

IFileOperation::DeleteItems 支持不同类型的输入。

只需传入您拥有的实例指针(IShellItemArray、、或),该IDataObject方法会将输入视为 a并调用,直到找到它理解的类型。IEnumShellItemsIPersistIDListDeleteItemsIUnknownQueryInterface

你可以想象实现看起来像这样:

HRESULT DeleteItems(IUnknown*p)
{
    if (!p->QueryInterface(IShellItemArray)) ...
    else if (!p->QueryInterface(IDataObject)) ...
    ...
    else if (!p->QueryInterface(IPersistIDList)) ...
    else return E_NOINTERFACE;
}
于 2019-11-14T01:05:59.673 回答