Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Drag&Drop pictures from WPD camera

169 views
Skip to first unread message

MikeHa

unread,
May 23, 2009, 9:34:01 PM5/23/09
to
Hy,

in C# project I'd like to get a picture from a WPD camera device via
drag&drop. I can transfer normal objects via WPD API from the WPD device
without any problems. But if I use drag&drop there is something missing.

Checking the Clipboard Data with ClipSpy I can see:
WPD NSE
WPD NSE PnPDevicePath
WPD NSE StoragePUID

With the WPD NSE data I can access the camera device and the storage object.
But how can I access the dragged picture or object?

There is also the "Shell IDList Array" which seems to contain the
WPD_OBJECT_PERSISTENT_UNIQUE_ID, but how can I interprete the "Shell IDList
Array"?

Thanks

bviksoe

unread,
May 24, 2009, 7:43:14 AM5/24/09
to

You are dragging from the device to your application?
What is the complete list of clipboard formats you see?


The Shell IDList Array is a list of IDs that identify the shell items
being dragged.
The structure is documented here:
http://msdn.microsoft.com/en-us/library/bb776902.aspx
http://msdn.microsoft.com/en-us/library/bb773212(VS.85).aspx

But ideally you will use something like:
SHCreateShellItemArrayFromDataObject
...to get the Shell Items and query them for the IStream - or their
IDataObject which may contain the desired image resource.

bjarke

MikeHa

unread,
May 24, 2009, 2:26:00 PM5/24/09
to
Hi, thanks for your reply.

Yes I'm dragging from the device to my application.

Clipspy reports the following formats:
Shell IDList Array
FileContents <Data unavailable>
FileGroupDescriptorW
WPD Storage Attributes
Preferred DropEffect


WPD NSE
WPD NSE PnPDevicePath
WPD NSE StoragePUID

Shell Object Offsets
UsingDefaultDragImage
DragImageBits
DragContext
InShellDragLoop

Yes I think using SHCreateShellItemArrayFromDataObject would be great, but
there is no corresponding C# version available, I already googled. My interop
knowledge is not that good, I already tried with the following:

[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError =
true)]
internal static extern int SHCreateShellItemArrayFromDataObject(
System.Runtime.InteropServices.ComTypes.IDataObject pdo,
ref Guid riid,
[MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppv);

by calling with

var mydata = data as
System.Runtime.InteropServices.ComTypes.IDataObject;
ShellHelper.IShellItemArray nativeShellItemArray;
retCode =
ShellHelper.SHCreateShellItemArrayFromDataObject(mydata, ref guid, out
nativeShellItemArray);

But it doesen't work, the return HResult codes says no interface:
E_NOINTERFACE = 0x80004002,

Maybe the defintion of nativeShellItemArray is wrong:

[ComImport,
Guid(ShellIIDGuid.IShellItemArray),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IShellItemArray
{
// Not supported: IBindCtx.
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
void BindToHandler(
[In, MarshalAs(UnmanagedType.Interface)] IntPtr pbc,
[In] ref Guid rbhid,
[In] ref Guid riid,
out IntPtr ppvOut);

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
void GetPropertyStore(
[In] int Flags,
[In] ref Guid riid,
out IntPtr ppv);

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
void GetPropertyDescriptionList(
[In] ref PropertyKey keyType,
[In] ref Guid riid,
out IntPtr ppv);

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
void GetAttributes(
[In] SIATTRIBFLAGS dwAttribFlags,
[In] SFGAO sfgaoMask,
out SFGAO psfgaoAttribs);

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
void GetCount(out uint pdwNumItems);

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
void GetItemAt(
[In] uint dwIndex,
[MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);

// Not supported: IEnumShellItems (will use GetCount and
GetItemAt instead).
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
void EnumItems([MarshalAs(UnmanagedType.Interface)] out IntPtr
ppenumShellItems);
}

As I said I'm no expert in Interop. The above code I wrote after looking at
the windows api codepack from:
http://code.msdn.microsoft.com/WindowsAPICodePack

Mike

"bviksoe" wrote:

> ....to get the Shell Items and query them for the IStream - or their

MikeHa

unread,
May 24, 2009, 7:22:00 PM5/24/09
to
Nearly perfect, got it somehow working now!

Part of the code:

var mydata = data as
System.Runtime.InteropServices.ComTypes.IDataObject;
ShellHelper.IShellItemArray nativeShellItemArray;

guid = new Guid(ShellIIDGuid.IShellItemArray);


retCode =
ShellHelper.SHCreateShellItemArrayFromDataObject(mydata, ref guid, out
nativeShellItemArray);

ShellHelper.IShellItem2 nativeShellItem;

if (CoreErrorHelper.Succeeded(retCode))
{
string displayname;

uint items = 0;

nativeShellItemArray.GetCount(out items);
if (items > 0)
{
for (uint item = 0; item < items; item++)
{
nativeShellItemArray.GetItemAt(item, out
nativeShellItem);

nativeShellItem.GetDisplayName(ShellHelper.SIGDN.SIGDN_DESKTOPABSOLUTEPARSING, out displayname);
Console.WriteLine("Parsingname: {0}",
displayname);
}

}
}


Using SHCreateShellItemArrayFromDataObject makes using the CIDA structure
obsolete and is much more clear.

Mike

Jim Barry

unread,
May 26, 2009, 5:34:53 AM5/26/09
to
MikeHa wrote:
> FileContents <Data unavailable>
> FileGroupDescriptorW

These are the ones you want. That way you can avoid the dependency on SHCreateShellItemArrayFromDataObject, which is not available on pre-Vista systems, and you can support a wider variety of drag-drop sources (e.g. Zip Folders).

CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR are described in the topic Bjarke linked to before:

http://msdn.microsoft.com/en-us/library/bb776902.aspx

--
Jim Barry, Microsoft MVP

0 new messages