Как получить функцию GetData IDataObject, не зная тип?
Я разработал функциональность, с помощью которой пользователь может перетаскивать вложенные вложения электронной почты в мое приложение. Я извлекаю удаленные имена вложений, передавая формат "FileGroupDescriptor" и используя формат "FileContents" для извлечения потока вложений. Это нормально работает в моей системе, но на некоторых другие парни системы эта функция не может извлечь данные вложения. Итак, я думал о реализации функции, где я не жестко кодировать формат типа и извлекать его из самого IDataObject. Есть ли способ сделать это? Пожалуйста, найдите ниже код, который я использую:
public object GetData(string format, bool autoConvert)
{
try
{
//handle the "FileGroupDescriptor" and "FileContents" format request in this class otherwise pass through to underlying IDataObject
switch (format)
{
case "FileGroupDescriptor":
//override the default handling of FileGroupDescriptor which returns a
//MemoryStream and instead return a string array of file names
IntPtr fileGroupDescriptorAPointer = IntPtr.Zero;
try
{
//use the underlying IDataObject to get the FileGroupDescriptor as a MemoryStream
Object o = underlyingDataObject.GetData(typeof(Object));
MemoryStream fileGroupDescriptorStream = (MemoryStream)this.underlyingDataObject.GetData("FileGroupDescriptor", autoConvert);
byte[] fileGroupDescriptorBytes = new byte[fileGroupDescriptorStream.Length];
fileGroupDescriptorStream.Read(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
fileGroupDescriptorStream.Close();
//copy the file group descriptor into unmanaged memory
fileGroupDescriptorAPointer = Marshal.AllocHGlobal(fileGroupDescriptorBytes.Length);
Marshal.Copy(fileGroupDescriptorBytes, 0, fileGroupDescriptorAPointer, fileGroupDescriptorBytes.Length);
//marshal the unmanaged memory to to FILEGROUPDESCRIPTORA struct
object fileGroupDescriptorObject = Marshal.PtrToStructure(fileGroupDescriptorAPointer, typeof(NativeMethods.FILEGROUPDESCRIPTORA));
NativeMethods.FILEGROUPDESCRIPTORA fileGroupDescriptor = (NativeMethods.FILEGROUPDESCRIPTORA)fileGroupDescriptorObject;
//create a new array to store file names in of the number of items in the file group descriptor
string[] fileNames = new string[fileGroupDescriptor.cItems];
//get the pointer to the first file descriptor
IntPtr fileDescriptorPointer = (IntPtr)((long)fileGroupDescriptorAPointer + Marshal.SizeOf(fileGroupDescriptorAPointer));
//loop for the number of files acording to the file group descriptor
for (int fileDescriptorIndex = 0; fileDescriptorIndex < fileGroupDescriptor.cItems; fileDescriptorIndex++)
{
//marshal the pointer top the file descriptor as a FILEDESCRIPTORA struct and get the file name
NativeMethods.FILEDESCRIPTORA fileDescriptor = (NativeMethods.FILEDESCRIPTORA)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.FILEDESCRIPTORA));
fileNames[fileDescriptorIndex] = fileDescriptor.cFileName;
//move the file descriptor pointer to the next file descriptor
fileDescriptorPointer = (IntPtr)((long)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
}
//return the array of filenames
return fileNames;
}
finally
{
//free unmanaged memory pointer
Marshal.FreeHGlobal(fileGroupDescriptorAPointer);
}
case "FileGroupDescriptorW":
//override the default handling of FileGroupDescriptorW which returns a
//MemoryStream and instead return a string array of file names
IntPtr fileGroupDescriptorWPointer = IntPtr.Zero;
try
{
//use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
MemoryStream fileGroupDescriptorStream = (MemoryStream)this.underlyingDataObject.GetData("FileGroupDescriptorW");
byte[] fileGroupDescriptorBytes = new byte[fileGroupDescriptorStream.Length];
fileGroupDescriptorStream.Read(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
fileGroupDescriptorStream.Close();
//copy the file group descriptor into unmanaged memory
fileGroupDescriptorWPointer = Marshal.AllocHGlobal(fileGroupDescriptorBytes.Length);
Marshal.Copy(fileGroupDescriptorBytes, 0, fileGroupDescriptorWPointer, fileGroupDescriptorBytes.Length);
//marshal the unmanaged memory to to FILEGROUPDESCRIPTORW struct
object fileGroupDescriptorObject = Marshal.PtrToStructure(fileGroupDescriptorWPointer, typeof(NativeMethods.FILEGROUPDESCRIPTORW));
NativeMethods.FILEGROUPDESCRIPTORW fileGroupDescriptor = (NativeMethods.FILEGROUPDESCRIPTORW)fileGroupDescriptorObject;
//create a new array to store file names in of the number of items in the file group descriptor
string[] fileNames = new string[fileGroupDescriptor.cItems];
//get the pointer to the first file descriptor
IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorWPointer + Marshal.SizeOf(fileGroupDescriptorWPointer));
//loop for the number of files acording to the file group descriptor
for (int fileDescriptorIndex = 0; fileDescriptorIndex < fileGroupDescriptor.cItems; fileDescriptorIndex++)
{
//marshal the pointer top the file descriptor as a FILEDESCRIPTORW struct and get the file name
NativeMethods.FILEDESCRIPTORW fileDescriptor = (NativeMethods.FILEDESCRIPTORW)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.FILEDESCRIPTORW));
fileNames[fileDescriptorIndex] = fileDescriptor.cFileName;
//move the file descriptor pointer to the next file descriptor
fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
}
//return the array of filenames
return fileNames;
}
finally
{
//free unmanaged memory pointer
Marshal.FreeHGlobal(fileGroupDescriptorWPointer);
}
case "FileContents":
//override the default handling of FileContents which returns the
//contents of the first file as a memory stream and instead return
//a array of MemoryStreams containing the data to each file dropped
//get the array of filenames which lets us know how many file contents exist
string[] fileContentNames = (string[])this.GetData("FileGroupDescriptor");
//create a MemoryStream array to store the file contents
MemoryStream[] fileContents = new MemoryStream[fileContentNames.Length];
//loop for the number of files acording to the file names
for (int fileIndex = 0; fileIndex < fileContentNames.Length; fileIndex++)
{
//get the data at the file index and store in array
fileContents[fileIndex] = this.GetData(format, fileIndex);
}
//return array of MemoryStreams containing file contents
return fileContents;
}
//use underlying IDataObject to handle getting of data
return this.underlyingDataObject.GetData(format, autoConvert);
}
catch (Exception ex)
{
}
}
Я вызываю вышеуказанную функцию, используя следующий код:
if (e.Data.GetDataPresent(DataFormats.FileDrop))
// drag drop from explorer to outlook DM Repository
filenames = (string[])(e.Data.GetData(DataFormats.FileDrop));
else
{
OutlookDataObject dataObject = new OutlookDataObject(e.Data);
filenames = (string[])dataObject.GetData("FileGroupDescriptor");
filestreams = (MemoryStream[])dataObject.GetData("FileContents");
}
1 ответ
Используйте метод IDataObject::EnumFormatEtc - см. https://msdn.microsoft.com/en-us/library/windows/desktop/ms683979(v=vs.85).aspx