Вопрос

I'm trying to implement a Windows Autoplay handler; according to the documentation and the examples I found, I'm supposed to query the IDataObject for the "Autoplay Enumerated IDList Array" clipboard format.

So I tried to do something like that:

[DllImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClipboardFormatW")]
public static extern uint RegisterClipboardFormat([MarshalAs(UnmanagedType.LPWStr)] String format);

private const string CFSTR_AUTOPLAY_SHELLIDLISTS = "Autoplay Enumerated IDList Array";
private static readonly uint AUTOPLAY_SHELLIDLISTS = RegisterClipboardFormat(CFSTR_AUTOPLAY_SHELLIDLISTS);

...

public int Drop(IDataObject pDataObj, int grfKeyState, Point pt, ref DropEffect pdwEffect)
{
    var fmt = new FORMATETC
    {
        cfFormat = (short)AUTOPLAY_SHELLIDLISTS,
        ptd = IntPtr.Zero,
        dwAspect = DVASPECT.DVASPECT_CONTENT,
        lindex = -1,
        tymed = TYMED.TYMED_HGLOBAL
    };

    int hr = pDataObj.QueryGetData(ref fmt);
    if (hr == S_OK)
    {
        ...
    }
    return 0;
}

But QueryGetData always returns S_FALSE (and GetData throws, obviously). So I tried to enumerate the available formats with EnumFormatEtc: it returns only one format it returns 4 formats, none of which is the same as the one I passed to QueryGetData (cfFormat values are -16238, 15, -16378 and -16377). If I use the first format from EnumFormatEtc, instead of AUTOPLAY_SHELLIDLISTS, everything works fine, but I don't think it's the right way to do it...

Could someone explain what is going on? Am I using the wrong format?

EDIT: apparently the first format returned from EnumFormatEtc is "Shell IDList Array"; clearly I can work with that, but what happened to "Autoplay Enumerated IDList Array"?

Это было полезно?

Решение

OK, I finally found a much easier way to do it, using the System.Windows.Forms.DataObject class:

    public int Drop(IDataObject pDataObj, int grfKeyState, Point pt, ref DropEffect pdwEffect)
    {
        try
        {
            var dataObj = new DataObject(pDataObj);
            if (dataObj.ContainsFileDropList())
            {
                StringCollection files = dataObj.GetFileDropList();

                // Do something with files...

            }
            return 0;
        }
        catch(Exception ex)
        {
            Trace.WriteLine(string.Format("Error: {0}", ex));
            return 1;
        }
    }

No need for any low-level COM interop (except the IDropTarget interface declaration)...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top