.net 接收从网页拖到WPF窗口的图像

.net 接收从网页拖到WPF窗口的图像,.net,wpf,winforms,drag-and-drop,bitmap,.net,Wpf,Winforms,Drag And Drop,Bitmap,我希望我的WPF应用程序成为拖放目标,并且我希望能够从任何网页拖动图像 当从网页拖动图像时,它显然是“DragImageBits”格式,可以反序列化为type。(我是如何定义它的,请参见问题的底部) 如何将其转换为WPF图像 这是我目前的尝试。(如果有人知道实现愿望的正确方法,我洗耳恭听) 此时,我得到一个类型为System.Runtime.InteropServices.ExternalException的异常,消息只是Generic GDI+error 有人知道我应该做什么吗 下面是支持类

我希望我的WPF应用程序成为拖放目标,并且我希望能够从任何网页拖动图像

当从网页拖动图像时,它显然是“DragImageBits”格式,可以反序列化为type。(我是如何定义它的,请参见问题的底部)

如何将其转换为WPF图像

这是我目前的尝试。(如果有人知道实现愿望的正确方法,我洗耳恭听)

此时,我得到一个类型为
System.Runtime.InteropServices.ExternalException
的异常,消息只是
Generic GDI+error

有人知道我应该做什么吗


下面是支持类的定义。我是从我的书里抄来的


以下是我学到的:

“DragImageBits”由windows shell提供,仅用于拖动光标,不用于最终数据。外壳通过调整大小和透明度将图像转换为适当的拖动光标

例如,如果拖动此图像:

SHDRAGIMAGE将呈现如下所示:

如果您真的想从SHDRAGIMAGE中提取图像,下面是代码。(部分吊离)

如果要将DragImageBits用于其预期用途(作为拖动图像),请参阅(存档),以获取一个简单的可下载示例


因此,“DragImageBits”实际上是在分散对实际问题的注意力,即接受从网页拖动的图像。 从网页拖动图像会变得复杂,因为Firefox、Chrome和IE9都提供了不同的格式集。此外,您还需要同时处理图像和图像超链接,并且它们的处理方式也会有所不同

Google和Firefox提供了一种“text/html”格式,它将一个html元素作为图像。Google将其作为ASCII字符串提供给您,Firefox将其作为unicode字符串提供给您。下面是我为处理它而编写的代码:

     System.Windows.IDataObject data = e.Data;
        string[] formats = data.GetFormats();


        if (formats.Contains("text/html"))
        {

            var obj = data.GetData("text/html");
            string html = string.Empty;
            if (obj is string)
            {
                html = (string)obj;
            }
            else if (obj is MemoryStream)
            {
                MemoryStream ms = (MemoryStream)obj;
                byte[] buffer = new byte[ms.Length];
                ms.Read(buffer, 0, (int)ms.Length);
                if (buffer[1] == (byte)0)  // Detecting unicode
                {
                    html = System.Text.Encoding.Unicode.GetString(buffer);
                }
                else
                {
                    html = System.Text.Encoding.ASCII.GetString(buffer);
                }
            }
            // Using a regex to parse HTML, but JUST FOR THIS EXAMPLE :-)
            var match = new Regex(@"<img[^/]src=""([^""]*)""").Match(html);
            if (match.Success)
            {
                Uri uri = new Uri(match.Groups[1].Value);
                SetImageFromUri(uri);
            }
        }
对于IE9,您可以处理“FileDrop”格式。这在IE9中运行良好。Chrome不支持它。Firefox确实支持它,但会将图像转换为位图,并将透明像素转换为黑色。因此,只有在“text.html”格式不可用时,才应处理“FileDrop”格式

    else if (formats.Contains("FileDrop"))
    {
        var filePaths = (string[])data.GetData("FileDrop");
        using (var fileStream = File.OpenRead(filePaths[0]))
        {
            var buffer = new byte[fileStream.Length];
            fileStream.Read(buffer, 0, (int)fileStream.Length);
            this.ImageBinary = buffer;
        }
    }
如果从IE9拖动图像超链接,则不提供“FileDrop”格式。我还不知道如何将IE9中的图像超链接中的图像拖到我的图像控件上


**额外信息** 如果您正在使用此示例,但仍需要将此二进制数据转换为图像,则以下是一段有用的代码片段:

                BitmapImage sourceImage = new BitmapImage();
                using (MemoryStream ms = new MemoryStream(imageBinary))
                {
                    sourceImage.BeginInit();
                    sourceImage.CacheOption = BitmapCacheOption.OnLoad;
                    sourceImage.StreamSource = ms;
                    sourceImage.EndInit();
                }

我也有同样的问题——我发现Firefox和IE9都提供了设备独立位图(DIB)格式。在这种情况下,不需要使用WebClient下载文件,因为我们可以访问熟悉的(位图)格式的文件。Firefox还公开了“FileDrop”格式,但在解析html和使用FileDrop格式的情况下,可以下载不一定是图像的对象。这对我帮助很大。谢谢你的发帖。正则表达式无法匹配许多有效的图像链接。我发现@“]+src=”“([^”“]*)”的效果更好一些。你真是个救命恩人。如果像我这样的其他人想直接从google images中拖动图像,请检查URI字符串,如果它以
“data”
开头,则这些字符串已经包含数据,不应下载到“this blog”的链接在此处可用:。顺便说一句:有用的问题和答案!
     System.Windows.IDataObject data = e.Data;
        string[] formats = data.GetFormats();


        if (formats.Contains("text/html"))
        {

            var obj = data.GetData("text/html");
            string html = string.Empty;
            if (obj is string)
            {
                html = (string)obj;
            }
            else if (obj is MemoryStream)
            {
                MemoryStream ms = (MemoryStream)obj;
                byte[] buffer = new byte[ms.Length];
                ms.Read(buffer, 0, (int)ms.Length);
                if (buffer[1] == (byte)0)  // Detecting unicode
                {
                    html = System.Text.Encoding.Unicode.GetString(buffer);
                }
                else
                {
                    html = System.Text.Encoding.ASCII.GetString(buffer);
                }
            }
            // Using a regex to parse HTML, but JUST FOR THIS EXAMPLE :-)
            var match = new Regex(@"<img[^/]src=""([^""]*)""").Match(html);
            if (match.Success)
            {
                Uri uri = new Uri(match.Groups[1].Value);
                SetImageFromUri(uri);
            }
        }
    private void SetImageFromUri(Uri uri)
    {
        string fileName = System.IO.Path.GetTempFileName();
        using (WebClient webClient = new WebClient())
        {
            webClient.DownloadFile(uri, fileName);
        }
        using (FileStream fs = File.OpenRead(fileName))
        {
            byte[] imageData = new byte[fs.Length];
            fs.Read(imageData, 0, (int)fs.Length);
            this.ImageBinary = imageData;
        }
        File.Delete(fileName);
    }
    else if (formats.Contains("FileDrop"))
    {
        var filePaths = (string[])data.GetData("FileDrop");
        using (var fileStream = File.OpenRead(filePaths[0]))
        {
            var buffer = new byte[fileStream.Length];
            fileStream.Read(buffer, 0, (int)fileStream.Length);
            this.ImageBinary = buffer;
        }
    }
                BitmapImage sourceImage = new BitmapImage();
                using (MemoryStream ms = new MemoryStream(imageBinary))
                {
                    sourceImage.BeginInit();
                    sourceImage.CacheOption = BitmapCacheOption.OnLoad;
                    sourceImage.StreamSource = ms;
                    sourceImage.EndInit();
                }