像Windows资源管理器一样执行拖放操作

时间:2018-08-01 09:13:19

标签: .net vb.net drag-and-drop

我有一个可以拖放n SVG文件的应用程序。这是用于Adobe XD之类的应用程序的工具(支持SVG文件)。执行基本的拖放操作非常简单。

Dim dataObj As New DataObject(DataFormats.FileDrop, New String() {_svgPath})
PictureBox.DoDragDrop(dataObj, DragDropEffects.Copy)

它有效!如果我想将文件拖放到资源管理器中,则一切正常。另外,如果我拖动n拖放一个“ .png”文件以绘画或一个字符串到编辑器:它也可以。

现在的问题是:当涉及其他第三方应用程序时,它将变得有些混乱。您想将SVG文件从应用程序拖放到Adobe XD吗?不,这行不通!您想将SVG文件从文件夹拖放到Adobe XD吗?这将正常工作。

这种混乱的情况不仅出现在Adobe XD中。它们有大量其他程序,使用资源管理器时可以进行“拖放”操作,但是“自己创建的”拖放操作失败。

我已经尝试了很多。使用不同的DataFormats,不同的DragDropEffects测试了它……没有任何效果。就像我错过了什么。我已经在GitHub上搜索了不同的DoDragDrop()函数,并在.NET Docs中进行了搜索,以查看是否缺少某些内容。

我在有关DoDragDrop()函数的System.Windows.Forms.Control的参考源中找到了这一点:

  

开始拖动操作。 allowedEffects确定可以进行哪些拖动操作。如果拖动操作需要与另一个进程中的应用程序互操作,则数据应该是基本托管类(字符串,位图或图元文件),或者是某些实现System.Runtime.Serialization.ISerializable的对象。数据也可以是实现System.Windows.Forms.IDataObject的任何对象。

但是此信息也没有真正帮助。

Windows资源管理器如何创建其DragDrop操作,如何在.Net中进行这样的DragDrop操作(如果在vb.net或c#中无关)?我需要对DataObject做更多的事情吗?改造吗?改变吗?

2 个答案:

答案 0 :(得分:1)

这些是涉及DataFormats.FileDrop数据类型的Drag&Drop操作的基本要求。
如果Windows GDI相关方法(主要是BitBlt)支持源文件类型,则包括源文件的缩略图图像。

开始Drag&Drop操作时-将鼠标拖动到PictureBox上-原始.svg文件路径被添加到专门的StringCollection类中。
然后,将StringCollection路径包括在使用DataObject方法传递到DoDragDrop方法的DataObject.SetFileDropList()集合中,并包含DragDropEffects的扩展选择。 />

此处使用的SVGImagePath字段是指原始.svg文件路径。

  

Win GDI图像源(Jpeg)已通过PhotoShop,FireFox,Windows Paint,Visual Studio图像编辑器进行了测试。
  .svg图片已通过FireFox和Edge测试。

.Net Version: 4.7.1
Visual Studio version: 15.7.5

Imports System.Collections.Specialized

Private SVGImagePath As String = "[Source SVG File]"

Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
    If sender IsNot Nothing AndAlso (e.Button = MouseButtons.Left) Then

        Dim dataObject As New DataObject()
        Dim FilePathsItems As New StringCollection()
        FilePathsItems.Add(SVGImagePath)

        Dim thumbCallback As Image.GetThumbnailImageAbort =
            Function()
                Return False
            End Function
        dataObject.SetImage(New Bitmap(PictureBox1.Image.GetThumbnailImage(64, 64, thumbCallback, IntPtr.Zero)))
        dataObject.SetFileDropList(FilePathsItems)
        ListBox1.DoDragDrop(dataObject, (DragDropEffects.All Or DragDropEffects.Link))
    End If
End Sub

C#原始代码:

using System.Collections.Specialized;

private string SVGImagePath = string.Empty;

private void pictureBox2_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        //Image.GetThumbnailImageAbort thumbCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback);
        //FilePathsItems.Add(((FileInfo)listBox1.SelectedItem).FullName);
        DataObject dataObject = new DataObject();
        StringCollection FilePathsItems = new StringCollection();
        FilePathsItems.Add(SVGImagePath);

        Image.GetThumbnailImageAbort thumbCallback = ()=> { return false; };
        dataObject.SetImage(new Bitmap(pictureBox2.Image.GetThumbnailImage(64, 64, thumbCallback, IntPtr.Zero)));
        dataObject.SetFileDropList(FilePathsItems);
        listBox1.DoDragDrop(dataObject, (DragDropEffects.All | DragDropEffects.Link));
    }
}

答案 1 :(得分:0)

吉米的答案是正确的。我在Jimi代码中的问题是缩略图图像的生成。您的目标应用程序可能会因此而阻止D&D操作。如果您等待几秒钟(也许是GetThumbnailImage花费时间),那么目标应用程序将允许该文件。我将个人密码留作答案。

Dim dataObj As New DataObject
Dim filePaths = New List(Of String) From {New System.IO.FileInfo(_svgPath).FullName}
Dim sc = New System.Collections.Specialized.StringCollection()
sc.AddRange(filePaths.ToArray())
dataObj.SetFileDropList(sc)
PictureBox.DoDragDrop(dataObj, DragDropEffects.Copy)

再次:特别感谢@Jimi的努力<3