Sign in to follow this  
midora

Drag & Drop ghost image

Recommended Posts

There is one small thing I'm missing in the drag and drop implementation. There is no ghost image if you are dragging an object on top of Paint.NET. Seems the Drag and Drop Helper interface is not used.

 

Typically you are just adding one line to OnDragEnter, OnDragOver, OnDragLeave and OnDragDop. I.e.

 

        protected override void OnDragEnter(DragEventArgs e)
        {
           // Your code here
            DropHelper.DragEnter(e);
        }
 

Here is a a DragDropHelperLib.cs to access the unmanaged com interfaces.

// Based on 'Shell Style Drag and Drop in .NET (WPF and WinForms)'
// http://blogs.msdn.com/b/adamroot/archive/2008/02/19/shell-style-drag-and-drop-in-net-wpf-and-winforms.aspx

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;

namespace DragDropHelperLib
{
    #region Native data structures

    [StructLayout(LayoutKind.Sequential)]
    public struct Win32Point
    {
        public int x;
        public int y;

        public Win32Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct Win32Size
    {
        public int cx;
        public int cy;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct ShDragImage
    {
        public Win32Size sizeDragImage;
        public Win32Point ptOffset;
        public IntPtr hbmpDragImage;
        public int crColorKey;
    }

    #endregion // Native data structures

    #region IDragSourceHelper

    [ComVisible(true)]
    [ComImport]
    [Guid("DE5BF786-477A-11D2-839D-00C04FD918D0")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDragSourceHelper
    {
        void InitializeFromBitmap(
            [In, MarshalAs(UnmanagedType.Struct)] ref ShDragImage dragImage,
            [In, MarshalAs(UnmanagedType.Interface)] System.Runtime.InteropServices.ComTypes.IDataObject dataObject);

        void InitializeFromWindow(
            [In] IntPtr hwnd,
            [In] ref Win32Point pt,
            [In, MarshalAs(UnmanagedType.Interface)] System.Runtime.InteropServices.ComTypes.IDataObject dataObject);
    }

    #endregion // IDragSourceHelper

    #region IDropTargetHelper

    [ComVisible(true)]
    [ComImport]
    [Guid("4657278B-411B-11D2-839A-00C04FD918D0")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDropTargetHelper
    {
        void DragEnter(
            [In] IntPtr hwndTarget,
            [In, MarshalAs(UnmanagedType.Interface)] System.Runtime.InteropServices.ComTypes.IDataObject dataObject,
            [In] ref Win32Point pt,
            [In] int effect);

        void DragLeave();

        void DragOver(
            [In] ref Win32Point pt,
            [In] int effect);

        void Drop(
            [In, MarshalAs(UnmanagedType.Interface)] System.Runtime.InteropServices.ComTypes.IDataObject dataObject,
            [In] ref Win32Point pt,
            [In] int effect);

        void Show(
            [In] bool show);
    }

    #endregion // IDropTargetHelper

    #region DragDropHelper

    [ComImport]
    [Guid("4657278A-411B-11d2-839A-00C04FD918D0")]
    public class DragDropHelper 
    {
    }

    #endregion // DragDropHelper

    public class DropHelper
    {
        public static void DragEnter(DragEventArgs e)
        {
            Win32Point wp = new Win32Point(e.X, e.Y);
            IDropTargetHelper dropHelper = (IDropTargetHelper)new DragDropHelper();
            dropHelper.DragEnter(IntPtr.Zero, (System.Runtime.InteropServices.ComTypes.IDataObject)e.Data, ref wp, (int)e.Effect);
        }

        public static void DragOver(DragEventArgs e)
        {
            Win32Point wp = new Win32Point(e.X, e.Y);
            IDropTargetHelper dropHelper = (IDropTargetHelper)new DragDropHelper();
            dropHelper.DragOver(ref wp, (int)e.Effect);
        }

        public static void DragLeave()
        {
            IDropTargetHelper dropHelper = (IDropTargetHelper)new DragDropHelper();
            dropHelper.DragLeave();
        }

        public static void DragDrop(DragEventArgs e)
        {
            Win32Point wp = new Win32Point(e.X, e.Y);
            IDropTargetHelper dropHelper = (IDropTargetHelper)new DragDropHelper();
            dropHelper.Drop((System.Runtime.InteropServices.ComTypes.IDataObject)e.Data, ref wp, (int)e.Effect);
        }
    }

    public class DragHelper
    {

        public static void Source(ShDragImage shdi, DataObject data)
        {
            IDragSourceHelper sourceHelper = (IDragSourceHelper)new DragDropHelper();
            sourceHelper.InitializeFromBitmap(ref shdi, data);
        }
    }

}

Share this post


Link to post
Share on other sites

I'm guessing, by "ghost image," he means a semi-transparent version of what you're dragging and dropping from a different program so you can see where it's going.

For example, click and drag your avatar within your browser.

Now try clicking and dragging the image over a paint.net window.

It's a cosmetic feature, as you can't really choose where you put the image when you drag into paint.net

Share this post


Link to post
Share on other sites

It's for sure just a cosmetic thing. It's about user experience.

 

In the moment if you are dragging a file from Windows Explorer (or other applications like Firefox) to Paint.NET then you will see a ghost image of the content of the file (or files). This ghost image disappears if you are reaching the border of the Paint.NET window because the Drag and Drop Helper is not supported in Paint.NET.

 

I would give the Drag & Drop Helper a chance.

Share this post


Link to post
Share on other sites

Here a screenshot of dragging the forum logo from the browser to Paint.NET.

It's the pixel before the mouse enters the area of the Paint.NET window.

So you still see the ghost image of the dragged item.

If the mouse is moved one more pixel to the left then the ghost image disappears and you will just see the mouse pointer with the rectangle and the copy/move/forbidden indicator.

 

post-79572-0-32420300-1392734633_thumb.j

 

Microsoft introduced this interface years ago in XP and I got never a problem supporting it in an application. The interface just allows the DropTarget to adapt the DragEventArgs.Effect settings so that the DragSource may react.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this