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 overlayIStream
andIStorage
references like that, the marshaller will try to marshal both. Your best bet is probably to just declare the field asIntPtr
in your declaration ofSTGMEDIUM
, and useMarshal.GetIUnknownForObject
to initialize it.