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?
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.