在不同的情况下拖拽图片

一、在一个WPF应用程序中,如果我们需要经图片从一个地方通过拖拽复制或者移动到应用程序中的另外一个地方,可以非常简单的使用Image 控件的Source 属性作为拖拽传递的数据。

private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Image img = e.Source as Image;
    DataObject data = new DataObject(DataFormats.Text, img.Source);
 
    DragDrop.DoDragDrop((DependencyObject)e.Source, data, DragDropEffects.Copy);
}
 
private void Image_Drop(object sender, DragEventArgs e)
{
    Image img = e.Source as Image;
    img.Source = (BitmapSource) e.Data.GetData(DataFormats.Text);
}



二、在两个不同的WPF应用程序中,要从一个应用程序中将图片通过拖拽复制到另外一个应用程序中,需要创建一个bitmap 类型的DataObject 作为拖拽传递的数据。

在源应用程序中启动拖拽:

private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Bitmap bitmap = ImageToBitmap(e.Source as System.Windows.Controls.Image);
 
    DataObject data = new DataObject(DataFormats.Bitmap, bitmap);
 
    DragDrop.DoDragDrop((DependencyObject)e.Source, data, DragDropEffects.Copy);
}


上面使用到的ImageToBitmap 函数代码如下:

private Bitmap ImageToBitmap(System.Windows.Controls.Image image)
{
    RenderTargetBitmap rtBmp = new RenderTargetBitmap((int)image.ActualWidth, (int)image.ActualHeight,
        96.0, 96.0, PixelFormats.Pbgra32);
 
    image.Measure(new System.Windows.Size((int)image.ActualWidth, (int)image.ActualHeight));
    image.Arrange(new Rect(new System.Windows.Size((int)image.ActualWidth, (int)image.ActualHeight)));
 
    rtBmp.Render(image);
 
    PngBitmapEncoder encoder = new PngBitmapEncoder();
    MemoryStream stream = new MemoryStream();
    encoder.Frames.Add(BitmapFrame.Create(rtBmp));
 
    // Save to memory stream and create Bitamp from stream
    encoder.Save(stream);
 
    return new System.Drawing.Bitmap(stream);
}

在目标应用程序中接收图片数据:

private void Window_Drop(object sender, DragEventArgs e)
{
    BitmapSource bmSource = (BitmapSource)e.Data.GetData(DataFormats.Bitmap);
    imgDropHere.Source = bmSource;
}


三、将图片从WPF应用程序拖入到Microsoft Word 中,需要创建一个加强元数据类型(enhanced metafile format)。

private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Bitmap bitmap = ImageToBitmap(e.Source as System.Windows.Controls.Image);
 
    DataObject data = new DataObject(DataFormats.EnhancedMetafile, MakeMetafileStream(bitmap));
 
    DragDrop.DoDragDrop((DependencyObject)e.Source, data, DragDropEffects.Copy);
}
ImageToBitmap 函数代码请看前面的介绍。MakeMetafileStream 函数是将Bitmap 转换为一个包含有Metafile 的流,这个流就是构造拖拽传递数据的参数。
private MemoryStream MakeMetafileStream(Bitmap image)
{
    Graphics graphics = null;
    Metafile metafile = null;
    var stream = new MemoryStream();
    try
    {
        using (graphics = Graphics.FromImage(image))
        {
            var hdc = graphics.GetHdc();
            metafile = new Metafile(stream, hdc);
            graphics.ReleaseHdc(hdc);
        }
        using (graphics = Graphics.FromImage(metafile))
        { graphics.DrawImage(image, 0, 0); }
    }
    finally
    {
        if (graphics != null)
        { graphics.Dispose(); }
        if (metafile != null)
        { metafile.Dispose(); }
    }
    return stream;
}



当程序接收到拖拽过来的数据的时候,我们还应该判断数据是不是我们需要的类型,否则不允许拖入。可以使用下面的代码判断:
private void Image_DragEnter(object sender, DragEventArgs e)
{
 
    if (e.Data.GetDataPresent(DataFormats.Bitmap))
        e.Effects = DragDropEffects.Copy;
    else
        e.Effects = DragDropEffects.None;
 
    e.Handled = true;
}
 
private void Image_DragOver(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.Bitmap))
        e.Effects = DragDropEffects.Copy;
    else
        e.Effects = DragDropEffects.None;
 
    e.Handled = true;
}
上面的代码中,当拖拽进入和在控件上面的时候通过e.Data.GetDataPresent 来判断数据是否是指定的类型,如果不是则设置e.Effects = DragDropEffects.None。其效果如下图。

最后说一个小技巧,使用键盘上的Esc键可以取消Window下的拖拽操作。当我们进行拖拽操作,拖到一半想取消的时候可以按Esc键取消操作。

阅读更多
个人分类: WPF
上一篇#695 – 实现一个简单的拖拽(Implementing Drag-and-Drop Behavior)
下一篇#705 – 拖拽可序列化类型的数据(Dragging a Custom Object Using Serialization as Format)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭