Получение имен файлов
Получить имена файлов легко. Просто позвоните:
dragEventArgs.Data.GetData("FileGroupDescriptorW")
это вернет MemoryStream
, который содержит FILEGROUPDESCRIPTORA
структуру. Это может быть проанализировано, чтобы получить имена файлов. Здесь и здесь - это ссылки на проекты в CodeProject, которые показывают два различных способа анализа FILEGROUPDESCRIPTORA
в C #, поэтому я не буду вдаваться в подробности. Я бы, вероятно, использовал технику, описанную в первом проекте.
Получение фактических данных
Чтобы получить фактические данные, вы используете формат FileContents
. К сожалению, вы должны либо использовать отражение для доступа к закрытым методам, либо написать какое-нибудь COM-взаимодействие самостоятельно. Проблема заключается в том, что для получения данных необходимо вызвать интерфейс System.Runtime.InteropServices.ComTypes.IDataObject
со структурой FORMATETC, для которой lindex установлен в индекс элемента. К сожалению, реализация System.Windows.DataObject всегда вызывает его с lindex = -1.
Самым простым решением, вероятно, является использование рефлексии для вызова частных членов WPF DataObject
. Однако предупредите, что это может привести к поломке вашего кода в будущих версиях NET Framework. Если это совершенно неприемлемо, другой вариант - вызвать функцию RegisterDragDrop
в ole32.dll
, чтобы зарегистрировать пользовательский IOleDropTarget
, а затем напрямую поговорить с COM IDataObject
, который передается. Это не очень сложно, но решение для отражения намного проще и, вероятно, будет работать для многих версий NET Framework, поэтому на этом я остановлюсь.
Вот что нужно сделать, чтобы получить FileContent для определенного индекса:
- Отобразите фактический класс объекта данных, чтобы найти метод с именем "GetData", который принимает четыре аргумента
- Если метод не был найден, подумайте еще раз, чтобы найти поле типа
System.Windows.IDataObject
, получите его значение и вернитесь к шагу 1 (рекурсия здесь безопасна)
- Используйте
MethodInfo.Invoke
для вызова «GetData», которое вы нашли с аргументами: «FileContents», false, ComTypes.DVASPECT, lindex
- Считать данные файла из возвращенного
MemoryStream
Вот суть кода для извлечения содержимого файла для данного индекса:
public MemoryStream GetFileContents(IDataObject dataObject, int index)
{
MethodInfo getData = (
from method in dataObject.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
where method.Name=="GetData" && method.GetParameters().Length==4
select method
).FirstOrDefault();
if(getData==null)
{
FieldInfo innerField = (
from field in dataObject.GetType().GetFields()
where field.FieldType == typeof(IDataObject)
select field
).FirstOrDefault();
if(innerField==null) throw new Exception("Cannot get FileContents from DataObject of type" + dataObject.GetType());
return GetFileContents((IDataObject)innerField.GetValue(dataObject), index);
}
return (MemoryStream)getData.Invoke(dataObject, new object[]
{
"FileContents", false,
System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT,
index
});
}