views:

553

answers:

1

I've been working on what sounds like simple functionality for way too long now. The idea is that I have an application with a TreeView. This treeview represents contents of a database organized into files and folders, much like Windows Explorer. So it makes sense that the user should be able to drag those files/folders out of my app and into Windows Explorer.

I decided that I should use an IStream if they drag a file or an IStorage if they drag a folder. After a very long time and learning way more than I ever wanted to know about Win32/COM (and a nudge from a very helpful person here), I finally have that IStream or IStorage created.

Then I found that to pass this IStream or IStorage off to Windows Explorer, I had to get it in an STGMEDIUM. Of course, the medium.tymed will be either IStream or IStorage, depending on which I'm using, but as I understand it the medium.unionmember must be a pointer to the IStream/IStorage. I've tried using the fixed keyword (but it's not blittable, of course), I've tried just converting the blasted thing to a byte array, but can't come up with a way to make that happen, I've tried using GCHandle to pin it (but it still isn't blittable), and several other things that didn't work.

So my question is this: Given IStorage s and STGMEDIUM m, how do I populate m.unionmember so that Windows Explorer will be happy and accept the drop?

+1  A: 

Normally, C unions are represented using StructLayout.Explicit in C#. This probably won't work in your case, however - while you can overlay IStream and IStorage references like that, the marshaller will try to marshal both. Your best bet is probably to just declare the field as IntPtr in your declaration of STGMEDIUM, and use Marshal.GetIUnknownForObject to initialize it.

Pavel Minaev
Thanks! I don't know how I missed GetIUnknownForObject... I think I'm going to have to break down and actually figure out what Marshaling is one day...