通过
IDataObject
接口:通过
IDataObject::GetData
读取文件,该接口应支持至少CFSTR_FILEDESCRIPTORW
、CFSTR_FILECONTENTS
和CFSTR_SHELLIDLIST
剪贴板格式。从IDataObject::GetData
请求CFSTR_FILECONTENTS
应创建一个用于访问数据的IStream
。当请求CFSTR_FILEDESCRIPTORW
时,通过设置FD_PROGRESSUI
标志来启用 UI。通过
ITransferSource
接口:通过请求
IShellItemResources
的ITransferSource::OpenItem
来读取文件。然后,IShellItemResources
应报告支持{4F74D1CF-680C-4EA3-8020-4BDA6792DA3C}
资源(表示该项有一个IStream
)。最后,通过父级ShellFolder::BindToObject
请求IStream
来访问数据。UI 由资源管理器自己处理,它总是显示。
IShellFolder::GetUIObjectOf
的IDataObject
和来自IShellFolder::CreateViewObject
的ITransferSource
,则始终使用通过IDataObject
的方法导致旧的复制GUI界面(如第一张截图所示)。我从跟踪日志中看到ITransferSource
被多次请求,但没有执行任何操作,它只是立即被释放和销毁。
那么我该如何强制资源管理器在从我的Shell命名空间扩展复制时显示漂亮的复制GUI界面呢?
这里可以找到一个最小化可复现的例子:https://github.com/BilyakA/SO_73938149
在处理 Minimal Reproducible example 时,我成功地使其可以同时支持 IDataObject 和 ITranfserSource 接口后,发生了以下情况:
- 取消注册 x64 构建的 SNE 示例(
regsvr32 /u
) - 注册 x32 构建的 SNE 示例(在 x64 Explorer 中无法工作,根目录未打开)
- 取消注册 x32
- 再次注册 x64。
我尝试过:
- 同时注册 x32 和 x64 SNE-仍然是旧 GUI
- 删除
Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Cached
中我的 NSE GUID 值,并在之后重新启动资源管理器。仍然是旧 GUI。
ITransferSource
。由于我一开始开发和测试时没有使用ITransferSource
,所以被缓存为我的NSE不支持它,即使我后来添加了它。而且某种方式注册32位重置了该缓存值。
IDataObject
和ITransferSource
,则会使用旧的用户界面。我认为我应该同时实现两者,因为我预计旧软件只能处理IDataObject
。另外,据我所知,拖放和复制粘贴也在很大程度上依赖于IDataObject
。最后,我发现系统中的默认文件夹都同时实现了这两个接口,那么我为什么不呢? - ElDoradoSHCreateDataObject(m_pidl, cidl, apidl, NULL, riid, ppv);
,不要向Shell提供的内容添加一个内部(损坏的)IDataObject
。您可以丢弃您的CDataObject
类,您永远不需要它,Shell为您提供了所有HIDA支持。其他事项:#2除非需要,否则不要实现ITransferMediumItem
。#3在ITransferSource::OpenItem
中只返回S_FALSE(未记录),并且放弃您的自定义IShellItemResources
实现。 - Simon Mourier