C#拖放问题

本文关键字:问题 拖放 | 更新日期: 2023-09-27 17:52:12

我有一个C#.NET 3.5应用程序,它允许从树中拖动项目,并将它们作为文件放到文件夹中。这是我的代码

String absolutePathToFile=...get absolute path
DataObject dataObject = new DataObject();
StringCollection paths = new StringCollection();
paths.Add(absolutePathToFile);
dataObject.SetFileDropList(paths);
DoDragDrop(dataObject, DragDropEffects.Copy);

除了与另一个通过拖放接受文件的C#应用程序交互时,这一操作效果很好。另一个C#应用程序具有以下DragOver 处理程序

if ((e.Data is DataObject) && (e.Data as DataObject).ContainsFileDropList())
{
    e.Effect = DragDropEffects.Copy;
}

由于e.数据是__ComObject而不是DataObject,因此从未执行该块。有趣的是,当我把一个文件从文件夹拖到第二个应用程序上时,它会把它看作DataObject。

如何使第一个C#应用程序中的DataObject在第二个C#应用中显示为DataObject?

C#拖放问题

我决定从IDataObjec t实现开始,使用.NET Interop实现IDataObject。然后定义了DROPFILES结构

[StructLayoutAttribute(LayoutKind.Sequential)]
internal struct _DROPFILES
{
    public Int32 pFiles;
    public Int32 X;
    public Int32 Y;
    public bool fNC;
    public bool fWide;
}

并实现填充所有OLE结构的代码。下面的函数返回我在DoDragDrop:中使用的IDataObject

DoDragDrop(GetDataObject(new String[] { file name }), DragDropEffects.Copy);

DataObject2 GetDataObject(String[] strFiles)
{
    byte[] bData;
    _DROPFILES df = new _DROPFILES();
    int intChar, intFile, intDataLen, intPos;
    IntPtr ipGlobal = IntPtr.Zero;
    // Calculate total data length
    intDataLen = 0;
    for (intFile = 0; intFile <= strFiles.GetUpperBound(0);intFile++)
    {
        intDataLen += strFiles[intFile].Length + 1;
    }
    // Terminating double zero
    intDataLen++;
    bData = new Byte[intDataLen];
    intPos = 0;
    // Build null terminated list of files
    for (intFile = 0; intFile <= strFiles.GetUpperBound(0); intFile++)
    {
        for (intChar = 0; intChar < strFiles[intFile].Length;intChar++)
        {
            bData[intPos++] = (byte)strFiles[intFile][intChar];
        }
        bData[intPos++] = 0;
    }
    // Terminating double zero
    bData[intPos++] = 0;
    // Allocate and get pointer to global memory
    int intTotalLen = Marshal.SizeOf(df) + intDataLen;
    ipGlobal = Marshal.AllocHGlobal(intTotalLen);
    if (ipGlobal == IntPtr.Zero)
    {
        return null;
    }
    // Build DROPFILES structure in global memory.
    df.pFiles = Marshal.SizeOf(df);
    df.fWide = false;
    Marshal.StructureToPtr(df, ipGlobal, true);
    IntPtr ipNew = new IntPtr(ipGlobal.ToInt32() + Marshal.SizeOf(df));
    Marshal.Copy(bData, 0, ipNew, intDataLen);
    short CF_HDROP = 15;
    System.Runtime.InteropServices.ComTypes.FORMATETC formatEtc;
    System.Runtime.InteropServices.ComTypes.STGMEDIUM stgMedium;
    formatEtc = new System.Runtime.InteropServices.ComTypes.FORMATETC();
    formatEtc.cfFormat = CF_HDROP;
    formatEtc.dwAspect = System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT;
    formatEtc.lindex = -1;
    formatEtc.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_HGLOBAL;
    stgMedium = new System.Runtime.InteropServices.ComTypes.STGMEDIUM();
    stgMedium.unionmember = ipGlobal;
    stgMedium.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_HGLOBAL;
    DataObject2 dobj = new DataObject2();
    dobj.SetData(ref formatEtc, ref stgMedium, false);
    return dobj;
}

有了新代码,第二个应用程序在e.Data中看到DataObject,我可以将该文件拖放到任何应用程序。只是现在资源管理器不接受文件。我的实现中是否遗漏了什么?