Я начал пытаться реализовать перетаскивание виртуальных файлов (из приложения C # 4 / WPF) с помощью этого учебного курса по коду проекта . Потратив некоторое время , пытаясь выяснить ошибку DV_E_FORMATETC , я понял, что мне нужно поддерживать формат данных «Shell IDList Array». Но, похоже, почти нет документации о том, что на самом деле делает этот формат.
После некоторого поиска я нашел эту страницу о расширенной передаче данных , в которой говорилось, что массив IDList-массивов Shell был указателем на структуру CIDA . Эта структура CIDA содержит количество PIDL и список смещений для них. Так что, черт возьми, PIDL? После дополнительного поиска, эта страница предполагает, что это указатель на ITEMIDLIST , который сам содержит один элемент, который является списком SHITEMID s.
Я еще кое-что прочитал, я до сих пор не могу сказать, для чего нужны несколько PIDL, но для каждого «уровня» в пути есть один SHITEMID. По крайней мере, это одна загадка разгадана.
Моей следующей идеей было попытаться перетащить файл из другого приложения с виртуальными файлами (WinSCP). Я только что вернул MemoryStream для этого формата. По крайней мере, я знаю, какой класс предоставить для этой вещи, но это совсем не помогает объяснить, что в нее вставить. Я попытался изучить этот MemoryStream на основе форматов, указанных в ссылках выше, но у меня ничего не получилось. Я только что получил данные об мусоре, и одно из полей 'cb' сообщило мне, что длина всего 18000 байт, когда весь поток составляет всего 539 байт.
Кроме того, при дальнейшем чтении эта страница , по-видимому, подразумевает, что данные, содержащиеся в PIDL, в действительности оказываются путями, а проверка содержимого упомянутой MemoryStream в шестнадцатеричном редакторе дает путь внутри мой локальный каталог Temp (в любом случае разбитый на части).
Кажется, что WinSCP просто использует расширение оболочки для обработки сбрасывания в проводнике, к чему я действительно не хочу прибегать. Однако у него есть альтернативный режим, в котором он прерывает перетаскивание до тех пор, пока он не перейдет во временную папку - это приемлемо для меня, но я не имею ни малейшего представления, как это сделать.
Мои вопросы сейчас:
- Что такое действительный член abID для SHITEMID? Эти виртуальные файлы существуют только в моей программе; Будет ли та вещь, которую они перетаскивают, передать позже «abID», когда он выполняет GetData? Должны ли они быть уникальными для системы?
- Как я могу управлять перетаскиванием и отменой позже, что делает WinSCP?
- Если бы мне пришлось реализовать расширение оболочки для этого, как бы я вообще это сделал? Я уверен, что могу легко найти объяснения теории расширения оболочки, но как бы я поддержал пользовательские PIDL или что-то еще?
Буду очень признателен за любую помощь или даже ссылки, которые объясняют, что я должен делать.
Редактировать: Итак, вот как я на самом деле это сделал в итоге:
Я удалил большую часть кода из учебника CodeProject выше, сохранив функции для создания FileGroupDescriptor. Затем я переопределил интерфейс .Net IDataObject (и на самом деле мне вообще не пришлось использовать интерфейс COM IDataObject). Затем я вынужден синхронно загрузить файл в фоновом режиме и передать MemoryStream обратно из GetData (). Удобно, что фактическое копирование находится в фоновом режиме, но в ожидании данных находится на переднем плане. Спасибо, исследователь. Любые достаточно большие файлы работают медленно, но сейчас они «работают», что больше, чем я могу сказать за последние несколько недель.
Я попытался передать класс PipeStream , который я использую для переводов внутри, но проводник не доволен этим:
- Он пытается искать, несмотря на то, что класс CanSeek имеет значение false.
- Он игнорирует размер, который я посылаю в FileGroupDescriptor, и просто загружает все, что находится в потоке прямо сейчас .
Итак, я не уверен, что идеальный случай действительно возможен. Тем не менее, спасибо за вашу помощь. Я даю награду JPW, потому что его ответы в конечном итоге ставят меня на правильный путь.