Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Following hours and hours of frustration with steam coming out of my ears, I finally arrived at a second solution to this problem. Exactly which solution is the most elegant is probably in the eyes of the beholder. I hope that Michael's and my solutions will both aid frustrated programmers and save them time when they embark on similar quests.</p> <p>First of all, one thing that did strike me was that Wordpad was able to receive the drag/drop images just out of the box. Thus the packaging of the file was probably not the problem, but there was perhaps something fishy going on at the receiving end.</p> <p>And fishy there was. It turns out there are seveal types of IDataObjects floating about the .Net framework. As Michael pointed out, OLE drag and drop support attempts to use .Net remoting when interacting between applications. This actually puts a System.Runtime.Remoting.Proxies.__TransparentProxy where the image is supposed to be. Clearly this is not (entirely) correct.</p> <p>The following article gave me a few pointers in the right direction:</p> <p><a href="http://blogs.msdn.com/adamroot/archive/2008/02/01/shell-style-drag-and-drop-in-net-wpf-and-winforms.aspx" rel="nofollow noreferrer">http://blogs.msdn.com/adamroot/archive/2008/02/01/shell-style-drag-and-drop-in-net-wpf-and-winforms.aspx</a></p> <p>Windows Forms defaults to System.Windows.Forms.IDataObject. However, since we're dealing with different processes here, I decided to give System.Runtime.InteropServices.ComTypes.IDataObject a shot instead.</p> <p>In the dragdrop event, the following code solves the problem:</p> <pre><code>const int CF_BITMAP = 2; System.Runtime.InteropServices.ComTypes.FORMATETC formatEtc; System.Runtime.InteropServices.ComTypes.STGMEDIUM stgMedium; formatEtc = new System.Runtime.InteropServices.ComTypes.FORMATETC(); formatEtc.cfFormat = CF_BITMAP; formatEtc.dwAspect = System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT; formatEtc.lindex = -1; formatEtc.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_GDI; </code></pre> <p>The two GetData functions only share the same name. One returns an object, the other is defined to return void and instead passes the info into the stgMedium <em>out</em> parameter:</p> <pre><code>(dea.Data as System.Runtime.InteropServices.ComTypes.IDataObject).GetData(ref formatEtc, out stgMedium); Bitmap remotingImage = Bitmap.FromHbitmap(stgMedium.unionmember); (sender as PictureBox).Image = remotingImage; </code></pre> <p>Finally, to avoid memory leaks, it's probably a good idea to call the OLE function ReleaseStgMedium:</p> <pre><code>ReleaseStgMedium(ref stgMedium); </code></pre> <p>That function can be included as follows:</p> <pre><code>[DllImport("ole32.dll")] public static extern void ReleaseStgMedium([In, MarshalAs(UnmanagedType.Struct)] ref System.Runtime.InteropServices.ComTypes.STGMEDIUM pmedium); </code></pre> <p>...and this code seems to work perfectly with drag and drop operations (of bitmaps) between two applications. The code could easily be extended to other valid clipboard formats and probably custom clipboard formats too. Since nothing was done with the packaging part, you can still dragdrop an image to Wordpad, and since it accepts bitmap formats, you can also drag an image from Word into the application.</p> <p>As a side note, dragging and dropping an image directly from IE does not even raise the DragDrop event. Strange.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload