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

Question about SHCreateShellFolderView and Drag and Drop.. Drop on NSE is fine.. but Drag from NSE (DropSource), is problem

172 views
Skip to first unread message

Sridhar Anupindi

unread,
Aug 7, 2004, 8:15:15 PM8/7/04
to
Hi All,

We have implemented a NameSpace Extension in c# which suppports Drag
& Drop. We have implemented DropTarget Interface succesfully and we
are able to Drag from Explorer to my NSE without any problems. I am
creating IID_IDropTarget both in CreateViewObject and GetUIObjectOf
methods. Please see Code below just for your reference.
-----------------------------
public void CreateViewObject(IWin32Window hwndOwner, ref Guid riid,
out IntPtr ppv)
{
if (NsExtension.IID_IShellView.Equals(riid))
{
ShellFolderViewCreate sfvc = new ShellFolderViewCreate(this,
this);
Marshal.ThrowExceptionForHR(Shell32.SHCreateShellFolderView(ref
sfvc, out ppv));

if (ppv == IntPtr.Zero)
{
throw new COMException();
}
}
else if (NsExtension.IID_IDropTarget.Equals(riid))
{
WindowsShell.Interop.IDataObject dataObject =
(WindowsShell.Interop.IDataObject) folderObj.DataObject;
ppv = Marshal.GetComInterfaceForObject(new
DropTargetImpl(folderObj,dataObject), typeof(IDropTarget));
}
else if (NsExtension.IID_IContextMenu.Equals(riid))
{
ppv = Marshal.GetComInterfaceForObject(new ContextMenuImpl(null,
folderObj), typeof(IContextMenu));
}
else
{
throw new COMException();
}
}
-------------------------
public void GetUIObjectOf(IWin32Window hwndOwner, uint cidl, IntPtr[]
apidl, ref Guid riid, IntPtr rgfReserved, out IntPtr ppv)
{
else if (riid.Equals(NsExtension.IID_IDropTarget))
{
if (cidl != 1)
{
throw new ArgumentOutOfRangeException("cidl", cidl, "Expected
exactly one PIDL to retrieve IDataObject");
}

IFolderObject obj =
folderObj.Restore(ItemIdList.Create(apidl[0]).GetItemData()[0]);
WindowsShell.Interop.IDataObject dataObject =
(WindowsShell.Interop.IDataObject)obj.DataObject;
ppv = Marshal.GetComInterfaceForObject(new
DropTargetImpl(folderObj, dataObject), typeof(IDropTarget));
}
else
{
throw new COMException();
}
}
-------------------------------------

Now the problem is while implementing DND from NSE to Explorer. I am
creating the DataObject under GetUIObjectOf with IID_DataObject. In
the constructor of my DataObject I am registering the custom formats,
HDrop etc with FORMATETC. In the GetUIOBjectOf method only we are
creating DropSource Object and then calling DoDragDrop method. The
sequence of events after this are DataObject.EnumFormatEtc() which
returns E_NOTIMPL, hence goes into DataObject.QueryGetData(). Here the
FORMATETC I am receiving as a parameter does not have any of the
Registered Clipboard Formats which I did in the Constructor, coz of
which I am unable to process my custom data.(but I am receiving the
following cfFormat values HDrop(15) and some large number(2011234319)
which I unable to understand.) I would really appreciate your help in
this regard.

Here is my Implementation of Interfaces and implementation..

----------
GetUIObjectOf Implementation
else if (riid.Equals(NsExtension.IID_IDataObject))
{
IFolderObject obj =
folderObj.Restore(ItemIdList.Create(apidl[0]).GetItemData()[0]);
WindowsShell.Interop.IDataObject dobj = new
DataObjectImpl(folderObj, apidl, apidl.Length);
WindowsShell.Interop.IDropSource dsrc = new DropSourceImpl();
int dwEffect = (int) (DragDropEffects.Copy|DragDropEffects.Move)
;
int pdwEffect = 0;
DoDragDrop(dobj,dsrc, dwEffect,out pdwEffect);
ppv = Marshal.GetComInterfaceForObject(dobj,
typeof(WindowsShell.Interop.IDataObject));
}
----------------
IDataObject........
{
[ComImport,
Guid("0000010e-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
CLSCompliant(false)]
public interface IDataObject
{
int GetData([In] ref FORMATETC pformatetcIn, ref STGMEDIUM pmedium);
void GetDataHere([In] ref FORMATETC pformatetc, [In, Out] ref
STGMEDIUM pmedium);
int QueryGetData([In] ref FORMATETC pformatetc);
int GetCanonicalFormatEtc([In] ref FORMATETC pformatectIn, [Out] out
FORMATETC pformatetcOut);
int SetData([In] ref FORMATETC pformatetc, [In] ref STGMEDIUM
pmedium, [In] bool fRelease);
int EnumFormatEtc([In] uint direction, [Out,
MarshalAs(UnmanagedType.Interface)] out IEnumFormatEtc
ppenumFormatEtc);
int DAdvise([In] ref FORMATETC pformatetc, [In] uint advf, [In,
MarshalAs(UnmanagedType.Interface)] IAdviseSink pAdvSink, [Out] out
uint pdwConnection);
int DUnadvise([In] uint dwConnection);
int EnumDAdvise([Out] out IEnumStatData ppenumAdvise);
}
--------------------------
using System;
using System.Windows.Forms;
using WindowsShell.Interop;
using System.Runtime.InteropServices;
namespace WindowsShell.Nspace
{
/// <summary>
/// Summary description for DataObjectImpl.
/// </summary>
internal class DataObjectImpl:WindowsShell.Interop.IDataObject
{
IFolderObject Root;

[DllImport("user32", EntryPoint="RegisterClipboardFormat")]
public static extern uint RegisterClipboardFormatA(string lpString);

[DllImport("user32", EntryPoint="GetClipboardFormatName")]
public static extern int GetClipboardFormatNameA(int wFormat, out
string lpString, int nMaxCount);

string CFSTR_PREFERREDDROPEFFECT =("Preferred DropEffect");
string CFSTR_SHELLIDLIST ="Shell IDList Array"; // CF_IDLIST
string CFSTR_FILECONTENTS ="FileContents"; //
CF_FILECONTENTS
string CFSTR_FILEDESCRIPTOR ="FileGroupDescriptor";
// This is my custom FOrmat...
string CFSTR_CWEXTENSIONDATA = "CWExtensionFormat";

uint m_PreferredDropEffect;
uint m_ShellIdList;
uint m_CWExtensionData;
uint m_FileDescriptor;
uint m_FileContents;
int m_iCurrent=0;

public int S_OK =unchecked((int)0x00000000L);
public int E_NOTIMPL=unchecked((int)0x80004001L);
public int E_INVALIDARG=unchecked((int)0x80070057L);
public int DV_E_DVASPECT=unchecked((int)0x8004006BL);
public int DV_E_TYMED=unchecked((int)0x80040069L);
int m_itemCount=0;
int m_cFormatsAvailable =4;
FORMATETC[] m_fmtetc;

internal DataObjectImpl(IFolderObject rootObj, IntPtr[] apidl, int
ItemCount)
{
//populate the dataobject
Root = rootObj;

m_CWExtensionData =
RegisterClipboardFormatA(CFSTR_CWEXTENSIONDATA);
m_PreferredDropEffect =
RegisterClipboardFormatA(CFSTR_PREFERREDDROPEFFECT);
m_ShellIdList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
//m_FileDescriptor =
RegisterClipboardFormatA(CFSTR_FILEDESCRIPTOR);
//m_FileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);

m_itemCount = ItemCount;

m_fmtetc = new FORMATETC[m_cFormatsAvailable];

SetDefFormatEtc(ref m_fmtetc [0],m_CWExtensionData);
SetDefFormatEtc(ref m_fmtetc [1],m_ShellIdList);
SetDefFormatEtc(ref m_fmtetc [2],(uint) CLIPFORMAT.CF_HDROP);
SetDefFormatEtc(ref m_fmtetc [3],m_PreferredDropEffect);

}
void SetDefFormatEtc(ref FORMATETC pFE, uint cfFormat)
{
pFE.cfFormat = cfFormat;
pFE.dwAspect =DVASPECT.DVASPECT_CONTENT;
pFE.tymed = TYMED.TYMED_ISTREAM;
pFE.lindex =-1;
pFE.ptd = 0;
}
int WindowsShell.Interop.IDataObject.GetData(ref FORMATETC
pformatetcIn, ref STGMEDIUM pmedium)
{
throw new NotImplementedException();
}
void WindowsShell.Interop.IDataObject.GetDataHere(ref FORMATETC
pformatetc, ref STGMEDIUM pmedium)
{
throw new NotImplementedException();
}
int WindowsShell.Interop.IDataObject.QueryGetData(ref FORMATETC
pformatetc)
{
throw new NotImplementedException();
}
int WindowsShell.Interop.IDataObject.GetCanonicalFormatEtc(ref
FORMATETC pformatectIn, out FORMATETC pformatetcOut)
{
throw new NotImplementedException();
}
int WindowsShell.Interop.IDataObject.SetData(ref FORMATETC
pformatetc, ref STGMEDIUM pmedium, bool fRelease)
{
throw new NotImplementedException();
}
int WindowsShell.Interop.IDataObject.EnumFormatEtc(uint direction,
out IEnumFormatEtc ppenumFormatEtc)
{
throw new NotImplementedException();
}
int WindowsShell.Interop.IDataObject.DAdvise(ref FORMATETC
pformatetc, uint advf, IAdviseSink pAdvSink, out uint pdwConnection)
{
throw new NotImplementedException();
}
int WindowsShell.Interop.IDataObject.DUnadvise(uint dwConnection)
{
throw new NotImplementedException();
}
int WindowsShell.Interop.IDataObject.EnumDAdvise(out IEnumStatData
ppenumAdvise)
{
throw new NotImplementedException();
}
}
}
----------------
IDropSource....
using System.Runtime.InteropServices;

namespace WindowsShell.Interop
{
/// <summary>
/// Summary description for IDropSource.
/// </summary>
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
GuidAttribute("00000121-0000-0000-C000-000000000046")]
public interface IDropSource
{
[PreserveSig]
uint QueryContinueDrag(
[MarshalAs(UnmanagedType.Bool)] bool fEscapePressed,
uint grfKeyState);
[PreserveSig]
uint GiveFeedback(
uint dwEffect);

}

}
-----------
using System;
using WindowsShell.Interop;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsShell.Nspace
{
internal class DropSourceImpl:WindowsShell.Interop.IDropSource
{
public uint DRAGDROP_S_DROP =unchecked((uint)0x00040100L);
public uint DRAGDROP_S_CANCEL=unchecked((uint)0x00040101L);
public uint DRAGDROP_S_USEDEFAULTCURSORS=unchecked((uint)0x00040102L);
internal DropSourceImpl()
{
}
uint IDropSource.QueryContinueDrag( bool fEscapePressed,uint
grfKeyState)
{
if(fEscapePressed == true)
{
return DRAGDROP_S_CANCEL;
}
return DRAGDROP_S_DROP;
}
uint IDropSource.GiveFeedback(uint dwEffect)
{

return DRAGDROP_S_USEDEFAULTCURSORS;
}
}
}
--------------------
Note: I am using the IShellView interface provided by
SHCreateShellFolderView() in NSE.

I really appreciate your help coz I am stuck here and unable to
proceed further. Thanks in Advance...

Sridhar Anupindi

Ari Berger

unread,
Aug 8, 2004, 7:19:46 AM8/8/04
to

> which I am unable to process my custom data.(but I am receiving the
> following cfFormat values HDrop(15) and some large number(2011234319)
> which I unable to understand.) I would really appreciate your help in
> this regard.
>
I can't really follow the C# code, but I agree that the large number
(2011234319) is just too big...
FORMATETC.cfFormat is defined as a CLIPFORMAT, #defined as a WORD, not a
DWORD.
The lower word looks like it is also 0x000F, or HDrop.
Hope this helps,
Ari


Henk Devos

unread,
Aug 9, 2004, 6:16:30 AM8/9/04
to
1. Why is EnumFormatEtc not implemented? I don't think you can ever get it
working like this.
2. The clipformats are CF_HDROP and a registered clipformat.
You might be asked for many formats that you don't support.
These will for example be formats for the drag image etc.
Some of these formats will be set first with SetData (if you do things
properly).
3. I don't understand why you call DoDragDrop when the IDataObject is
requested?
You are only requested to provide an interface, not to start a drag and drop
operation.
Note that the interface may be asked for many purposes other than drag and
drop (for example to enable/disable the copy command in the Edit menu). I
don't think you want to start a drag and drop operation when a menu is being
displayed.
What you should do is just return the IDataObject and let the sell start the
drag and drop operations (which will include the SetData calls).

--
Henk Devos
www.whirlingdervishes.com

"Sridhar Anupindi" <sanu...@gmail.com> wrote in message
news:dc23f516.0408...@posting.google.com...

> file://populate the dataobject


> Root = rootObj;
>
> m_CWExtensionData =
> RegisterClipboardFormatA(CFSTR_CWEXTENSIONDATA);
> m_PreferredDropEffect =
> RegisterClipboardFormatA(CFSTR_PREFERREDDROPEFFECT);
> m_ShellIdList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);

> file://m_FileDescriptor =
> RegisterClipboardFormatA(CFSTR_FILEDESCRIPTOR);
> file://m_FileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);

Sridhar Anupindi

unread,
Aug 9, 2004, 12:52:03 PM8/9/04
to
Ari & Henk,

Thank you so much for immediate responses.

Ari...
You were absolutely right. We changed the CLIPFORMAT from DWORD (uint
in my case) to WORD (ushort) and now I am able to see my Formats when
I am Dragging it along.

Henk ...


> 1. Why is EnumFormatEtc not implemented? I don't think you can ever get it
> working like this.

We did implement the EnumFormatEtc. How ever we did only constructor
and for all the methods (Next, Skip etc) we are returning E_NOTIMPL
from there. Is it ok we do it this way.. or do we have to implement
all the methods also..?

> 3. I don't understand why you call DoDragDrop when the IDataObject is
> requested?

I do understand that this may not be a right place to call the
DoDragDrop. As I said earlier we are implementing
SHCreateShellFolderView as our folderview and not custom shellview
implementation. Hence we are not sure where to implement the
DoDragDrop. If we had a shellview we know that we can implement it in
LVN_BEGINDRAG method. But in this SHCreateShellFolderView we are not
sure where to implement it? Can you throw some light on this.

Thanks once again.

Thanks

Sridhar Anupindi

Henk Devos

unread,
Aug 9, 2004, 6:05:36 PM8/9/04
to

"Sridhar Anupindi" wrote

> We did implement the EnumFormatEtc. How ever we did only constructor
> and for all the methods (Next, Skip etc) we are returning E_NOTIMPL
> from there. Is it ok we do it this way.. or do we have to implement
> all the methods also..?

You will have to implement the whole thing.
Not a lot of work really.
Also don't forget the Reset, it might actually be used.
I don't think the Skip will ever be called, as it seems to be quite useless.

> I do understand that this may not be a right place to call the
> DoDragDrop. As I said earlier we are implementing
> SHCreateShellFolderView as our folderview and not custom shellview
> implementation. Hence we are not sure where to implement the
> DoDragDrop. If we had a shellview we know that we can implement it in
> LVN_BEGINDRAG method. But in this SHCreateShellFolderView we are not
> sure where to implement it? Can you throw some light on this.
>

The shell will do this for you.
Typically like you say in the handler for LVN__BEGINDRAG, the shell will ask
for your IDataObject and call DoDragDrop.


--
Henk Devos
www.whirlingdervishes.com


Sridhar Anupindi

unread,
Aug 10, 2004, 4:24:03 PM8/10/04
to
Thanks Henk. It did the trick. Now I am not calling the DoDragDrop and
also commented the DropSource Implimentation. If I understand
correctly, when we use
SHCreateShellFolderView it would not be necessary to call DoDragDrop
and subsequently , no need to implement DropSource.

As you mentioned now we are implementing all the methods of
IEnumFormatEtc. please see the implementation below. The problem here
I am facing is, when I drag the mouse outside my window to another
Explorer window or Desktop, I get calls to DataObject.QueryGetData,
and GetData, but the Icon is still displaying with a circle and cross
around it ( DragDropEffects.None).

We are even implementing the EnumFormatEtc and DataObject in a
separate class as it can be a problem (through some newsgroups).

Please help us out.

Thanks Again for Everybody's Time.

Sridhar Anupindi

IDataObject.EnumFormatEtc method
----------
int WindowsShell.Interop.IDataObject.EnumFormatEtc(uint a, ref
WindowsShell.Interop.IEnumFormatEtc b)
{
//throw new NotSupportedException();
//return E_NOTIMPL;
switch (a)
{
case 1:
//int rajesh =
SHCreateStdEnumFmtEtc((uint)m_cFormatsAvailable,m_fmtetc,out b);//(new
EnumFormatEtcImpl(m_fmtetc,m_cFormatsAvailable);
b = new EnumFormatEtcImpl(m_fmtetc, m_cFormatsAvailable);
break;

case 2:
default:
b=null;
break;
}
if (b==null)
{
return E_NOTIMPL;
}
return S_OK;
}
-------------------------
EnumFormatEtcImplimentation

internal class EnumFormatEtcImpl : IEnumFormatEtc
{
public int E_NOTIMPL=unchecked((int)0x80004001L);
public int S_OK=unchecked((int)0x00000000L);
public int S_FALSE=unchecked((int)0x00000001L);
public int E_OUTOFMEMORY=unchecked((int)0x8007000EL);
public int E_INVALIDARG=unchecked((int)0x80070057L);
int m_cItems;
FORMATETC[] m_pStrFE;
int m_iCurrent;

internal EnumFormatEtcImpl(FORMATETC[] pFE,int numberItems)
{
m_cItems = numberItems;
m_pStrFE = new FORMATETC[numberItems];
m_pStrFE = pFE;
m_iCurrent = 0;

}
int WindowsShell.Interop.IEnumFormatEtc.Next(uint celt, FORMATETC[]
rgelt, uint pceltFetched)
{
uint copied = 0;

// copy the FORMATETC structures into the caller's buffer
while(m_iCurrent < m_cItems && copied < celt)
{
rgelt[copied] = m_pStrFE[m_iCurrent];
copied++;
m_iCurrent++;
}

// store result
if(0 != pceltFetched)
pceltFetched = copied;

// did we copy all that was requested?
return (copied == celt) ? S_OK : S_FALSE;

}
void WindowsShell.Interop.IEnumFormatEtc.Skip(uint celt)
{
if((m_iCurrent + (int)celt) >= m_cItems)
{
//return S_FALSE;
}
else
{
m_iCurrent += (int)celt;
}
//return S_OK;
}
void WindowsShell.Interop.IEnumFormatEtc.Reset()
{
m_iCurrent=0;
}
void WindowsShell.Interop.IEnumFormatEtc.Clone(out IEnumFormatEtc
ppenum)
{
EnumFormatEtcImpl pNew;

ppenum = null;

// Create the clone.
pNew = new EnumFormatEtcImpl(m_pStrFE, m_cItems);
if (null == pNew)
{
//return E_OUTOFMEMORY;
}
ppenum = pNew;
}
}
----------------------------------


"Henk Devos" <in...@dontspamme.regxplor.com> wrote in message news:<09ydnVjruJ8...@scarlet.biz>...

---------

Sridhar Anupindi

unread,
Aug 10, 2004, 5:11:38 PM8/10/04
to

Please help us out.

Sridhar Anupindi

internal class EnumFormatEtcImpl : IEnumFormatEtc
{
public int E_NOTIMPL=unchecked((int)0x80004001L);

ppenum = null;

---------

Henk Devos

unread,
Aug 10, 2004, 5:19:02 PM8/10/04
to
What I don't see is which data formats you are offering?

--
Henk Devos
www.whirlingdervishes.com

"Sridhar Anupindi" <sanu...@gmail.com> wrote in message

news:dc23f516.04081...@posting.google.com...


> Thanks Henk. It did the trick. Now I am not calling the DoDragDrop and
> also commented the DropSource Implimentation. If I understand
> correctly, when we use
> SHCreateShellFolderView it would not be necessary to call DoDragDrop
> and subsequently , no need to implement DropSource.
>
> As you mentioned now we are implementing all the methods of
> IEnumFormatEtc. please see the implementation below. The problem here
> I am facing is, when I drag the mouse outside my window to another
> Explorer window or Desktop, I get calls to DataObject.QueryGetData,
> and GetData, but the Icon is still displaying with a circle and cross
> around it ( DragDropEffects.None).
>
> We are even implementing the EnumFormatEtc and DataObject in a
> separate class as it can be a problem (through some newsgroups).
>
> Please help us out.
>
> Thanks Again for Everybody's Time.
>
> Sridhar Anupindi
>
> IDataObject.EnumFormatEtc method
> ----------
> int WindowsShell.Interop.IDataObject.EnumFormatEtc(uint a, ref
> WindowsShell.Interop.IEnumFormatEtc b)
> {

> file://throw new NotSupportedException();
> file://return E_NOTIMPL;
> switch (a)
> {
> case 1:
> file://int rajesh =

> file://return S_FALSE;
> }
> else
> {
> m_iCurrent += (int)celt;
> }
> file://return S_OK;


> }
> void WindowsShell.Interop.IEnumFormatEtc.Reset()
> {
> m_iCurrent=0;
> }
> void WindowsShell.Interop.IEnumFormatEtc.Clone(out IEnumFormatEtc
> ppenum)
> {
> EnumFormatEtcImpl pNew;
>
> ppenum = null;
>
> // Create the clone.
> pNew = new EnumFormatEtcImpl(m_pStrFE, m_cItems);
> if (null == pNew)
> {

> file://return E_OUTOFMEMORY;

Sridhar Anupindi

unread,
Aug 10, 2004, 6:37:27 PM8/10/04
to
Hi,

>>As you mentioned now we are implementing all the methods of
>>IEnumFormatEtc. please see the implementation below. The problem
here
>>I am facing is, when I drag the mouse outside my window to another
>>Explorer window or Desktop, I get calls to DataObject.QueryGetData,
>>and GetData, but the Icon is still displaying with a circle and
cross
>>around it ( DragDropEffects.None).

>>We are even implementing the EnumFormatEtc and DataObject in a
>>separate class as it can be a problem (through some newsgroups).

I was able to solve this problem. Actually we did not set the folder
or file attributes of cancopy/canmove. Hence this DragDropEffects.None
was appearing. Once I set these attributes to the folderobject or file
object, then I was able to get proper Icons and proper events are also
being raised. Thanks once again for your precious time in looking at
my problems.

Thanks

Sridhar Anupindi

"Henk Devos" <in...@dontspamme.regxplor.com> wrote in message news:<09ydnVjruJ8...@scarlet.biz>...

0 new messages