Drag & Drop для специальных папок - PullRequest
2 голосов
/ 14 ноября 2011

У меня есть приложение, которое позволяет пользователям перетаскивать файлы или целые папки в специальную «область перетаскивания», после чего все файлы обрабатываются.Приложение разрабатывается с использованием WPF, и это конкретное представление XAML устанавливает для параметра «AllowDrop» значение true и обрабатывает событие Drop в выделенном коде.

Все работает для обычных файлов и стандартных папок Windows.Однако если пользователь удаляет специальную папку Windows (например, «Изображения», «Видео»), эта функция не работает.Казалось бы, это потому, что содержимое DragEventArgs.Data не является перечислением DataFormats.FileDrop.Это не относится к другим папкам или файлам.

Мой код для обработки удаления частично:

private void OnDrop(object Sender, DragEventArgs E)
{
    if (E.Data.GetDataPresent(DataFormats.FileDrop))
    {
        var _droppedFilePaths = E.Data.GetData(DataFormats.FileDrop, true) as string[];

        // Process the files....
    }
}

Есть ли способ определить, что данные удаления содержат Windows7 библиотек изображений и карта обратно к ее фактическому пути?

1 Ответ

0 голосов
/ 14 ноября 2011

Используя решение, описанное здесь , я написал следующий метод:

const string ShellIdListArrayName = "Shell IDList Array";

static IEnumerable<string> GetPathsFromShellIDListArray(IDataObject data)
{
    if (data.GetDataPresent(ShellIdListArrayName))
    {
        var ms = (MemoryStream)data.GetData(ShellIdListArrayName);
        byte[] bytes = ms.ToArray();

        IntPtr p = Marshal.AllocHGlobal(bytes.Length);
        Marshal.Copy(bytes, 0, p, bytes.Length);
        uint cidl = (uint)Marshal.ReadInt32(p, 0);

        int offset = sizeof(uint);
        IntPtr parentpidl = (IntPtr)((int)p + (uint)Marshal.ReadInt32(p, offset));
        StringBuilder path = new StringBuilder(256);
        SHGetPathFromIDList(parentpidl, path);

        for (int i = 1; i <= cidl; ++i)
        {
            offset += sizeof(uint);
            IntPtr relpidl = (IntPtr)((int)p + (uint)Marshal.ReadInt32(p, offset));
            IntPtr abspidl = ILCombine(parentpidl, relpidl);
            if (SHGetPathFromIDList(abspidl, path) != 0)
            {
                yield return path.ToString();
            }
            ILFree(abspidl);
        }
    }
}

[DllImport("shell32.dll")]
public static extern int SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath); 

[DllImport("shell32.dll")]
public static extern IntPtr ILCombine(IntPtr pidl1, IntPtr pidl2);

[DllImport("shell32.dll")]
public static extern void ILFree(IntPtr pidl);

Вы можете просто передать e.Data из вашего обработчика событий в этот метод, и вы получитепоследовательность путей (при условии, что у элементов, конечно, есть путь ... например, "Мой компьютер" не имеет пути)

...