我开始尝试使用此代码项目教程实现虚拟文件的拖放(来自C#4 / WPF应用程序)。 在花了一些时间试图找出DV_E_FORMATETC错误后,我发现我需要支持“Shell IDList Array”数据格式。 但是关于这种格式实际上做了什么似乎只有零文档。

经过一番搜索后,我在高级数据传输中找到了这个页面,它说Shell IDList Array是一个指向CIDA结构的指针。 然后,此CIDA结构包含PIDL的数量以及它们的偏移列表。 那究竟是什么PIDL? 经过一些搜索之后, 这个页面有点暗示它是一个指向ITEMIDLIST的指针,它本身包含一个SHITEMID列表的成员。

我做了一些阅读,我仍然无法分辨多个PIDL是什么,但路径中的每个“级别”都有一个SHITEMID。 至少那个谜团已经解决了。

我的下一个想法是尝试使用虚拟文件(WinSCP)从另一个应用程序拖动文件。 我刚刚为这种格式安装了一个MemoryStream。 至少我知道要为这个东西提供什么类,但这根本不能解释放入它的内容。 我尝试根据上面链接中的格式检查这个MemoryStream,但是我没有成功。 我刚拿回垃圾数据,其中一个'cb'字段告诉我,当整个流只有539字节时,它是18000字节长。

此外,在进一步阅读时, 这个页面似乎暗示PIDL中包含的数据实际上是一个路径,并且在十六进制编辑器中检查所述MemoryStream的内容在我的本地Temp目录中产生了一个路径(分成几部分,无论如何)。

似乎WinSCP只是使用shell扩展来处理在资源管理器上的丢弃,这是我真的不想诉诸的。 但是,它有一个替代模式,它会中止dragdrop,直到它转移到临时文件夹 - 这对我来说是可以接受的,但我不知道如何做到这一点。

我现在的问题是:

  1. 什么是SHITEMID的有效“abID”成员? 这些虚拟文件仅与我的程序一起存在; 他们被拖动的东西会在以后执行GetData时传回“abID”吗? 他们必须是系统独特的吗?
  2. 如何管理WinSCP执行的中止和重做后续拖放操作?
  3. 如果我必须为此实现一个shell扩展,我怎么能这样做呢? 我确信我可以轻松找到shell扩展理论的解释,但我如何支持自定义PIDL或其他什么?

任何帮助甚至链接解释我应该做什么将不胜感激。

编辑:所以这就是我最终实际做到的方式:

我从上面的CodeProject教程中删除了大部分代码,保留了创建FileGroupDescriptor的功能。 然后我重新实现了.Net IDataObject接口(实际上,我根本不必使用COM IDataObject接口)。 然后我被迫在后台同步下载文件,并从GetData()传回MemoryStream。 方便的是,实际复制在后台,但等待数据在前台。 谢谢,探险家。 任何相当大的文件都很慢,但是现在它“有效”,这比过去几周我说的还要多。

我尝试传递我在内部使用的PipeStream类进行传输,但是explorer对此不满意:

  • 它试图寻求,尽管这个类有CanSeek是假的。
  • 它忽略了我在FileGroupDescriptor,只是下载什么,现在流中的发送大小。

所以,我不确定理想的情况是否真的可行。 不过,谢谢你的帮助。 我正在给予JPW赏金,因为他的回复最终让我走上了正确的道路。

#1楼 票数:3

我认为http://www.codeproject.com/KB/miscctrl/FileBrowser.aspx上的 C#文件浏览器可以为您提供最大的帮助。

这些文章非常宝贵。

Edanmo.ShellExtensions是绝对必备的。 http://www.mvps.org/emorcillo/en/code/shell/shellextensions.shtml

请注意,其中一些COM接口已在.NET 2.0中定义。 (我没有检查4.0,但我怀疑微软是否添加了对Shell / COM接口的任何额外支持。)

额外的东西

找到了!

完整的白痴编写命名空间扩展指南 - 第一部分网址http://www.codeproject.com/kb/shell/namespcextguide1.aspx 你在找什么?

#2楼 票数:2 已采纳

免责声明 :我既不是Windows Shell编程专家也不是COM编程专家,特别是在使用.NET的COM编程中。

免责声明2 :Shell编程相当复杂,Windows资源管理器可能会崩溃。 (请务必阅读有关调试shell扩展的MSDN上的信息。)

这是我能回答你的问题:

  1. SHITEMID的abID值由包含相应项的文件夹确定。 因此,没有有效或无效的信息,因为此数据仅对文件夹有效。 Windows资源管理器将传递此数据以标识特定项目。 abID不能是系统唯一的,但它在包含文件夹中可能是唯一的(虽然这不能保证)。 在某些情况下,SHITEMID可能会被持久化,因此在某些情况下它必须在重新启动后有效(因为应该避免在abID中使用此内存引用)。
  2. 据我了解,只有在需要实际数据时才会调用IDataObject :: GetData(我可能错了)。 所以它应该没问题,如果你将数据提取到GetData中的临时文件并将PIDL返回到该文件(请参阅http://support.microsoft.com/kb/132750/en-us ,尽管我记得有这个方法提供了一个方便的方法,但我不记得它的名字)。 不幸的是,我无法看到何时删除临时文件的好方法(作为最后的手段,你可以在销毁IDataObject时执行此操作,但这将导致可能不再需要的临时文件)。
  3. 您可能需要支持自定义PIDL(包括自定义PIDL管理器)并实现自定义IShellFolder。 但是,关于shell扩展的大多数文档都是针对C ++的,很多函数都没有很好地记录或根本没有记录。 有关PIDL的更多信息,我建议您阅读http://msdn.microsoft.com/en-us/library/cc144090.aspx 此外,您应该在Internet上搜索“Shell命名空间扩展”,因为可能有关于该主题的一些信息。 另请参阅Windows SDK提供的有关此主题的示例。

我希望一些信息对你有用。

编辑 :您还可以适当地实现QueryGetData和EnumerableFormatEtc,以指示您的对象不支持相关格式。 也许Windows资源管理器会尝试不同的格式。

编辑2 :虽然你已经确定了一个解决方案,但这里有一些关于如何异步拖放的信息(对于大文件),也许你(或者至少有人在寻找一个类似问题的答案,谁读取发现它很有用: http//msdn.microsoft.com/en-us/library/bb776904(VS.85).aspx #async

#3楼 票数:0

你看过这篇文章吗? 如何将虚拟文件从您的应用程序拖动到Windows资源管理器中源代码使用c ++,但它可以帮助您了解所有内容的工作原理。

  ask by JustABill translate from so

未解决问题?本站智能推荐:

1回复

拖放到资源管理器会导致无效的FORMATETC(DV_E_FORMATETC)错误

我正在尝试使用这个出色的示例来实现将虚拟文件拖放到Windows资源管理器中。 但是,这个错误使我受阻。 朝向底部,内部void System.Runtime.InteropServices.ComTypes.IDataObject.GetData(ref System.Runtime.In
2回复

将大型虚拟文件从 C# 拖放到 Windows 资源管理器

我有一个 C# WPF 应用程序,其中有一个部分用作 FTP 客户端,列出远程服务器上的文件并允许用户下载它们。 我希望用户能够将文件列表中的文件拖放到他们自己的机器上(即拖放到 Windows 资源管理器外壳中)。 为了实现这一点,我使用了Delay 博客中的VirtualFileDataObj
2回复

使用IStorage / IStream从C#拖放到Windows资源管理器

我一直在研究听起来像简单功能的东西。 我的想法是我有一个带有TreeView的应用程序。 此树视图表示组织到文件和文件夹中的数据库的内容,非常类似于Windows资源管理器。 因此,用户应该能够将这些文件/文件夹拖出我的应用程序并进入Windows资源管理器。 我决定如果他们拖动文件
1回复

使用C#从Windows拖放编写Windows资源管理器克隆

我试图在C#/ Visual Studio中创建一个Window Explorer克隆(希望它看起来尽可能接近本机资源管理器),并且我需要能够将文件从该资源管理器拖放到Windows。 谁能将我链接到任何此类项目的良好起点? 此外,任何有关如何执行此操作的常规技巧都将不胜感激。
1回复
2回复

WPF:将虚拟文件拖放到Windows资源管理器中

我正在开发一个类似于dropbox的应用程序,我在WPF列表视图中显示远程文件。 我想拖动这些元素并将其放入Windows资源管理器中。 我见过这样的代码: 但是你可能认为,那些文件还没有在本地系统上,在复制它们之前我需要连接到服务器,下载并解压缩文件。 像ftp客户端一样。
1回复

如何向所有Windows资源管理器实例添加按钮?

我正在尝试向任何Windows资源管理器实例中的现有工具栏之一添加按钮。 经过大量研究,我发现BHO(浏览器辅助对象)是连接的最佳方法 到Windows资源管理器。 我的问题是: 那是正确的方法吗? 在BHO的SetSite中,我获得了comObject,即资
1回复

在资源管理器和您的应用程序之间拖放时,如何知道您的应用程序目录?

我有一个小的命令行应用程序工具xyz.exe ,它接受文件名f作为参数,然后调用一个程序abc.exe ,该程序与xyz.exe位于同一文件夹中,并带有一些数据作为参数加f 。 想法是将一些文件从Windows资源管理器拖放到我的程序中,以便它使用适当的参数调用abc.exe 。 当我说