在我的 .NET Windows 窗体上实现从 Chrome 拖放

Posted

技术标签:

【中文标题】在我的 .NET Windows 窗体上实现从 Chrome 拖放【英文标题】:Implementing drag-drop from Chrome on my .NET Windows form 【发布时间】:2011-09-01 19:50:05 【问题描述】:

Google Chrome 有一个方便的功能,我可以单击下载链接并将其拖到 Windows 资源管理器窗口中,然后放下。删除后,Chrome 会下载文件并显示在我删除它的位置。

我希望能够从 Google Chrome 拖放到我的应用程序中,但似乎并不那么简单。我有一个名为 gridFiles 的 DataGridView,以及以下代码:

Private Sub gridFiles_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles gridFiles.DragDrop
    If e.Data.GetDataPresent(DataFormats.FileDrop) Then
        Dim DroppedFiles() As String = e.Data.GetData(DataFormats.FileDrop)
        If Not DroppedFiles Is Nothing Then
            For Each file As String In DroppedFiles
                MsgBox(file)
            Next
        End If
    End If
End Sub

Private Sub gridFiles_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles gridFiles.DragEnter
    If e.Data.GetDataPresent(DataFormats.FileDrop) Then
        e.Effect = DragDropEffects.All
    End If

End Sub

当我从 Windows 资源管理器中将文件拖放到其中时,一切正常,并且每个被删除的文件都会出现一个消息框。但是,当我从 Chrome 中删除时,什么也没有发生。原因是DroppedFiles 等于Nothinge.Data.GetData 似乎没有返回任何东西。我用e.Data.GetFormats()检查了格式,它返回FileDropFileNameFileNameW,正如预期的任何文件丢弃。

我很确定正在发生的是 Chrome 说它有一些文件以便 DragEnter 起作用,但由于它尚未下载文件,DragDrop 无法完成,因此 Chrome 不返回任何文件。我怀疑在 Windows 资源管理器上下文中,Chrome 会以某种方式获取该窗口的路径并稍后将文件复制到那里。

所以我的问题是......

如何欺骗 Chrome 浏览器进入我的应用程序?我通过以某种方式为 Chrome 提供一个它认为已删除文件的临时文件夹来实现这一点,并且我的应用程序将监视该文件夹中的新文件并在下载后将它们拉入。我只需要找到一种方法让 Chrome “知道”那个文件夹。

或者,如果我能获得所删除内容的 URL,那也很好。然后我可以用我的程序下载文件。

非常感谢任何和所有建议。谢谢。


编辑: 所以看来,使用常规 URL,我确实得到了正确的拖入 UniformResourceLocator 格式。我看到的行为发生在 Gmail 中的下载链接上。它可能发生在其他地方,但我不确定。当一个 gmail 附件从 Gmail 拖到我的应用程序中时,我得到一个 FileDrop。

做一些更多的挖掘,似乎Gmail正在使用锚标记的download_url属性。我以前从未听说过。也许这只是他们添加的额外属性?

在任何情况下,由于我的应用程序主要用于电子邮件附件,因此我需要一种方法让幻像 FileDrop 工作,如上所述。我无法使用 Spy++。发生掉落时,它似乎没有显示任何消息。 (我也欢迎任何关于这个问题的建议。)

编辑 #2: 以下是有关 Gmail 如何利用拖放操作文件的更多信息:http://www.thecssninja.com/javascript/gmail-dragout

【问题讨论】:

如果我能得到 URL... 仅限于 pemalink url @Luis,你是什么意思? 在某些下载(不是永久链接 url)上,您的应用将没有必要的会话状态(cookie)来访问所需的文件。 您可能想要检查e.Data.GetFormats() 返回的值,而不是依赖DataFormats.FileDrop。做一些快速测试,它看起来像"UniformResourceLocator"(甚至"Text")格式使e.Data.Get(...)返回一个MemoryStream,其中包含指向纯文本拖动链接的URL。也许这是需要进一步调查的事情。 @WraithNath 你可以看看 Chromium 源代码。这可能会提供更多答案。 【参考方案1】:

关于奇怪的拖放行为,我自己已经把数公里的头发从我的脑海中拉了出来。 Sixlettervariables 提到的 Spy++ 可能是一个好主意。另一种方法是查看我在 SO 上的一个 Q/As 中的讨论:

Drag and Drop between Instances of the same Windows Forms Application

根据我自己的经验,我似乎记得从浏览器拖放是一个安全问题,因此处理方式不同。希望这会有所帮助。

编辑:

也许这回答了你的问题:

http://www.vbforums.com/showthread.php?t=529211

【讨论】:

关于让 Spy++ 工作的任何建议?我无法让它显示任何拖放消息。 对不起,我只知道我有类似的问题,发现浏览器的东西非常受限。如果你明白这一点,我将在我自己的一个应用程序中实现它的一个版本:) 不幸的是,看起来我无法解决这个问题,呵呵。 +100 赏金仅剩 2 天,我什至不知道从哪里开始追踪这个。我能想到的唯一想法是在我的表单上实际放置一些资源管理器组件,但这并不理想。我什至不确定它会起作用。 我编辑了我的答案。也许链接中的解决方案适合你。【参考方案2】:

您是否考虑过使用 Spy++ 来查看从 Chrome 发送到 Windows 资源管理器的消息? Spy++ 具有消息记录功能,过去曾帮助我处理奇怪的行为。您可以启用 WM_DROPFILES 等的日志记录。

【讨论】:

是的,我使用了 Spy++,但没有看到任何消息,直到下降之后,然后它只是 MOUSEMOVE 和什么不是。 (事实上​​,我只是发布了一个单独的问题!)我会回去看看是否有过滤器或启用的东西。 我也无法让 Spy++64/32 生成 WM_DROPFILES 消息,但我使用的是 64 位机器,这可能会使事情复杂化。【参考方案3】:

奇怪的是,我只在从 Chrome 中拖动文件时获得快捷方式。

无论如何,如果Chrome使用虚拟源进行拖放,即下载文件并在拖放完成时生成内容,则必须实现shell接口IDropTarget。我感觉文件内容可能通过 .NET Drag&Drop 不支持的 IStream 传输。

也许这个http://msdn.microsoft.com/en-us/library/bb776904%28VS.85%29.aspx#copying 和这个Drag and drop virtual files using IStream 应该会让你走上正确的道路。

【讨论】:

以上是关于在我的 .NET Windows 窗体上实现从 Chrome 拖放的主要内容,如果未能解决你的问题,请参考以下文章

如何在 asp.net Web 窗体上实现 Ninject 或 DI?

vs2015中的c#windows窗体应用程序怎么使用OpenGL?

C# 转换继承的通用接口

如何在c#中避免多个windows窗体实例

将异步数据从网页传递到我的窗体 C# .NET 应用程序

在我的 Windows 窗体应用程序中遇到 Sqlcompact 数据库问题