我开始尝试使用此代码项目教程实现虚拟文件的拖放(来自 C# 4/WPF 应用程序)。在花了一些时间试图找出 DV_E_FORMATETC错误后,我发现我需要支持“Shell IDList Array”数据格式。但是关于这种格式的实际作用似乎几乎为零。
经过一番搜索,我发现这个关于高级数据传输的页面说 Shell IDList Array is a pointer to a CIDA structure。然后,此 CIDA 结构包含 PIDL 的数量以及它们的偏移量列表。那么PIDL到底是什么?经过一番搜索,这个页面有点暗示它是一个指向ITEMIDLIST的指针,它本身包含一个成员,它是一个SHITEMID的列表。
我做了更多的阅读,我仍然无法判断多个 PIDL 的用途,但是路径中的每个“级别”都有一个 SHITEMID。至少这是解决了一个谜。
我的下一个想法是尝试使用虚拟文件 (WinSCP) 从另一个应用程序中拖动文件。我刚刚得到了这种格式的 MemoryStream。至少我知道要为这个东西提供什么类,但这对解释要放什么东西根本没有帮助。我尝试根据上面链接中的格式检查此 MemoryStream,但没有成功。我刚取回垃圾数据,其中一个“cb”字段告诉我,当整个流只有 539 个字节时,它的长度为 18000 个字节。
此外,在进一步阅读后,此页面似乎暗示 PIDL 中包含的数据实际上是一条路径,并且在十六进制编辑器中检查所述 MemoryStream 的内容会在我的本地 Temp 目录中产生一条路径(分成几部分,反正)。
似乎 WinSCP 只是使用一个 shell 扩展来处理资源管理器的丢弃,我真的不想诉诸于此。但是,它有另一种模式,在它传输到临时文件夹之前中止拖放 - 这对我来说是可以接受的,但我一点也不知道该怎么做。
我现在的问题是:
- 什么是 SHITEMID 的有效“abID”成员?这些虚拟文件只存在于我的程序中;当它执行GetData时,它们会被拖到后面传递“abID”吗?它们必须是系统唯一的吗?
- 我如何管理 WinSCP 所做的中止和稍后重做的拖放操作?
- 如果我必须为此实现一个 shell 扩展,我该怎么做呢?我确信我可以很容易地找到 shell 扩展理论的解释,但是我将如何支持自定义 PIDL 或其他什么?
任何帮助甚至解释我应该做什么的链接将不胜感激。
编辑:所以这就是我最终是如何做到的:
我从上面的 CodeProject 教程中删除了大部分代码,保留了用于创建 FileGroupDescriptor 的函数。然后我重新实现了 .Net IDataObject 接口(实际上,我根本不必使用 COM IDataObject 接口)。然后我被迫在后台同步下载文件,并从 GetData() 传回 MemoryStream。方便的是,实际复制在后台,但等待数据在前台。谢谢,探险家。任何相当大的文件都很慢,但现在它“有效”,这比我过去几周所能说的要多。
我确实尝试过传递我在内部用于传输的PipeStream类,但资源管理器对此并不满意:
- 尽管这个类的 CanSeek 是假的,它还是会尝试寻找。
- 它忽略了我在 FileGroupDescriptor 中发送的大小,只是立即下载流中的任何内容。
所以,我不确定理想的情况是否真的可行。不过,感谢您的所有帮助。我将赏金给 JPW,因为他的回复最终让我走上了正确的道路。