Ответ 1
Вот что я узнал:
"DragImageBits" предоставляется оболочкой Windows и предназначен только для курсора перетаскивания, а не для конечных данных. Оболочка преобразует изображение в соответствующий курсор перетаскивания через изменение размера и прозрачность.
Например, если вы перетащите это изображение:
SHDRAGIMAGE будет выглядеть так:
Если вы действительно хотите извлечь изображение из SHDRAGIMAGE, вот код. (Частично снят с этот ответ)
MemoryStream imageStream = data.GetData("DragImageBits") as MemoryStream;
imageStream.Seek(0, SeekOrigin.Begin);
BinaryReader br = new BinaryReader(imageStream);
ShDragImage shDragImage;
shDragImage.sizeDragImage.cx = br.ReadInt32();
shDragImage.sizeDragImage.cy = br.ReadInt32();
shDragImage.ptOffset.x = br.ReadInt32();
shDragImage.ptOffset.y = br.ReadInt32();
shDragImage.hbmpDragImage = new IntPtr(br.ReadInt32()); // I do not know what this is for!
shDragImage.crColorKey = br.ReadInt32();
int stride = shDragImage.sizeDragImage.cx * 4;
var imageData = new byte[stride * shDragImage.sizeDragImage.cy];
// We must read the image data as a loop, so it in a flipped format
for (int i = (shDragImage.sizeDragImage.cy - 1) * stride; i >= 0; i -= stride)
{
br.Read(imageData, i, stride);
}
var bitmapSource = BitmapSource.Create(shDragImage.sizeDragImage.cx, shDragImage.sizeDragImage.cy,
96, 96,
PixelFormats.Bgra32,
null,
imageData,
stride);
Если вы хотите использовать DragImageBits по назначению (как изображение перетаскивания), см. этот блог для простого, загружаемого примера,
Таким образом, "DragImageBits" был в значительной степени отвлечен от реальной проблемы, которая заключается в том, чтобы принять изображение, перетаскиваемое с веб-страницы.
Перетаскивание изображения с веб-страницы осложняется, потому что Firefox, Chrome и IE9 предоставляют вам другой набор форматов. Кроме того, вы хотите обрабатывать как изображение, так и гиперссылку изображений, и они обрабатываются по-разному.
Google и Firefox предоставляют формат "text/html", который дает вам один HTML-элемент в качестве изображения. Google предоставляет его как строку ASCII, и Firefox предоставляет ее вам как строку юникода. Итак, вот код, который я написал для его обработки:
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);
}
}
В этом случае регулярное выражение будет обрабатывать как прямой образ, так и гиперссылку изображения.
И моя функция SetImageFromUri
:
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);
}
Для IE9 вы можете обрабатывать формат "FileDrop" . Это хорошо работает в IE9. Chrome не поддерживает его. Firefox поддерживает его, но преобразует изображение в растровое изображение и преобразует прозрачные пиксели в черный. По этой причине вы должны обрабатывать только формат "FileDrop" , если формат "text.html" недоступен.
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;
}
}
Формат "FileDrop" не предоставляется, если вы перетаскиваете гиперссылку изображения из IE9. Я не понял, как перетащить изображение из гиперссылки изображения в IE9 на мой контроль изображения.
Дополнительные сведения
Если вы используете этот пример, но все равно нужно преобразовать эти двоичные данные в изображение, здесь полезный фрагмент кода:
BitmapImage sourceImage = new BitmapImage();
using (MemoryStream ms = new MemoryStream(imageBinary))
{
sourceImage.BeginInit();
sourceImage.CacheOption = BitmapCacheOption.OnLoad;
sourceImage.StreamSource = ms;
sourceImage.EndInit();
}