我一直在尝试将 Gmail 附件从 Chrome 拖放到我的应用程序中。
可以将文件从电子邮件拖到桌面并在那里创建附件,所以我知道这一定是可能的。
我已经能够让它读取文件名,但是当我从数据对象读取 FileContents 时,我得到一个带有该文件链接的互联网快捷方式。
有人以前做过这个工作吗?目前的代码是针对 .txt 文件进行硬编码的
我的主要 DataObjectWrapper 类如下:
字符太多,无法全部发布,但主要方法是:
public object GetDataNative(string format, bool autoConvert)
{
switch (format)
{
case CFSTR_FILEDESCRIPTOR_A:
IntPtr fileGroupDescriptorAPointer = IntPtr.Zero;
try
{
//use the underlying IDataObject to get the FileGroupDescriptor as a MemoryStream
MemoryStream fileGroupDescriptorStream = (MemoryStream)this.underlyingDataObject.GetData(CFSTR_FILEDESCRIPTOR_A, 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;
//get the pointer to the first file descriptor
IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorAPointer + Marshal.SizeOf(fileGroupDescriptor.cItems));
NativeMethods.FILEDESCRIPTORA[] fileDescriptors = new NativeMethods.FILEDESCRIPTORA[fileGroupDescriptor.cItems];
//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));
fileDescriptors[fileDescriptorIndex] = fileDescriptor;
//move the file descriptor pointer to the next file descriptor
fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
}
fileGroupDescriptor.fgd = fileDescriptors;
//return the array of filenames
return fileGroupDescriptor;
}
finally
{
//free unmanaged memory pointer
Marshal.FreeHGlobal(fileGroupDescriptorAPointer);
}
case CFSTR_FILEDESCRIPTOR_W:
IntPtr fileGroupDescriptorWPointer = IntPtr.Zero;
try
{
//use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
MemoryStream fileGroupDescriptorStream = (MemoryStream)this.underlyingDataObject.GetData(CFSTR_FILEDESCRIPTOR_W);
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;
//get the pointer to the first file descriptor
IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorWPointer + Marshal.SizeOf(fileGroupDescriptor.cItems));
NativeMethods.FILEDESCRIPTORW[] fileDescriptiors = new NativeMethods.FILEDESCRIPTORW[fileGroupDescriptor.cItems];
//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));
fileDescriptiors[fileDescriptorIndex] = fileDescriptor;
//move the file descriptor pointer to the next file descriptor
fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
}
fileGroupDescriptor.fgd = fileDescriptiors;
//return the array of filenames
return fileGroupDescriptor;
}
finally
{
//free unmanaged memory pointer
Marshal.FreeHGlobal(fileGroupDescriptorWPointer);
}
case CFSTR_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(CFSTR_FILEDESCRIPTOR_W);
//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;
case CFSTR_INETURL_A:
//use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
MemoryStream UniformResourceLocatorStream = (MemoryStream)this.underlyingDataObject.GetData(CFSTR_INETURL_A);
byte[] UniformResourceLocatorBytes = new byte[UniformResourceLocatorStream.Length];
UniformResourceLocatorStream.Read(UniformResourceLocatorBytes, 0, UniformResourceLocatorBytes.Length);
UniformResourceLocatorStream.Close();
string url = null;
if (UniformResourceLocatorBytes[1] == 0)
url = Encoding.Unicode.GetString(UniformResourceLocatorBytes);
else
url = Encoding.ASCII.GetString(UniformResourceLocatorBytes);
return url;
case CFSTR_INETURL_W:
//use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
MemoryStream UniformResourceLocatorWStream = (MemoryStream)this.underlyingDataObject.GetData(CFSTR_INETURL_W);
byte[] UniformResourceLocatorWBytes = new byte[UniformResourceLocatorWStream.Length];
UniformResourceLocatorWStream.Read(UniformResourceLocatorWBytes, 0, UniformResourceLocatorWBytes.Length);
UniformResourceLocatorWStream.Close();
string urlW = null;
if (UniformResourceLocatorWBytes[1] == 0)
urlW = Encoding.Unicode.GetString(UniformResourceLocatorWBytes);
else
urlW = Encoding.ASCII.GetString(UniformResourceLocatorWBytes);
return urlW;
case TEXT_X_MOZ_URL:
//use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
MemoryStream textMozStream = (MemoryStream)this.underlyingDataObject.GetData(TEXT_X_MOZ_URL);
byte[] textMozBytes = new byte[textMozStream.Length];
textMozStream.Read(textMozBytes, 0, textMozBytes.Length);
textMozStream.Close();
string urlText = null;
if (textMozBytes[1] == 0)
urlText = Encoding.Unicode.GetString(textMozBytes);
else
urlText = Encoding.ASCII.GetString(textMozBytes);
return urlText;
case "text/html":
//use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
MemoryStream dataFormatStream = (MemoryStream)this.underlyingDataObject.GetData("text/html");
byte[] dataFormatBytes = new byte[dataFormatStream.Length];
dataFormatStream.Read(dataFormatBytes, 0, dataFormatBytes.Length);
dataFormatStream.Close();
string formatText = null;
if (dataFormatBytes[1] == 0)
formatText = Encoding.Unicode.GetString(dataFormatBytes);
else
formatText = Encoding.ASCII.GetString(dataFormatBytes);
return formatText;
}
//use underlying IDataObject to handle getting of data
return this.underlyingDataObject.GetData(format, autoConvert);
}
我可以从中获取相当多的数据,但与将其放在桌面上不同:
private void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] dataFormats = e.Data.GetFormats();
Dictionary<string, object> dataDictionary = new Dictionary<string, object>();
foreach (string dataFormat in dataFormats)
{
dataDictionary.Add(dataFormat, e.Data.GetData(dataFormat));
Debug.WriteLine(
String.Format("Data Format: {0} Has data: {1} Data: {2}",
dataFormat,
dataDictionary[dataFormat] != null ? "Yes" : "No",
dataDictionary[dataFormat] != null ? dataDictionary[dataFormat] : string.Empty));
}
DataObjectWrapper dataWrapper = new DragDropTest.DataObjectWrapper(e.Data);
DataObjectWrapper.NativeMethods.FILEGROUPDESCRIPTORW fileGroupDescriptorW = dataWrapper.GetFileGroupDescriptorW();
string url = dataWrapper.GetUniformResourceLocatorA();
string urlw = dataWrapper.GetUniformResourceLocatorW();
string mozUrl = dataWrapper.GetTextMozURL();
string textHTML = dataWrapper.GetTExtHtml();
Stream[] streams = dataWrapper.GetFileContents();
byte[] buffer = new byte[1024];
int received = 0;
FileStream fileStream = File.OpenWrite(@"c:\temp\hello.txt");
using (Stream input = streams[0])
{
int size = input.Read(buffer, 0, buffer.Length);
while (size > 0)
{
fileStream.Write(buffer, 0, size);
received += size;
size = input.Read(buffer, 0, buffer.Length);
}
}
fileStream.Flush();
fileStream.Close();
return;
}
我已经阅读并尝试了以下链接:
http://dlaa.me/blog/post/9913083 http://dlaa.me/blog/post/9913083
使用 VirtualFileDataObject 通过 IStream 拖放大型虚拟文件 https://stackoverflow.com/questions/22700195/drag-and-drop-large-virtual-files-with-istream-using-virtualfiledataobject
将大型虚拟文件从 C# 拖放到 Windows 资源管理器 https://stackoverflow.com/questions/12410114/drag-and-drop-large-virtual-files-from-c-sharp-to-windows-explorer
https://msdn.microsoft.com/en-us/library/windows/desktop/bb776902(v=vs.85).aspx#CFSTR_FILECONTENTS https://msdn.microsoft.com/en-us/library/windows/desktop/bb776902(v=vs.85).aspx#CFSTR_FILECONTENTS
https://msdn.microsoft.com/en-us/library/windows/desktop/bb776904(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/bb776904(v=vs.85).aspx
https://dlaa.me/blog/post/9923072 https://dlaa.me/blog/post/9923072
使用 IStream 拖放虚拟文件 https://stackoverflow.com/questions/1187444/drag-and-drop-virtual-files-using-istream
https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-wpf-and-winforms/ https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-wpf-and-winforms/
在我的 .NET Windows 窗体上实现 Chrome 的拖放 https://stackoverflow.com/questions/6125921/implementing-drag-drop-from-chrome-on-my-net-windows-form
https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-part-3/ https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-part-3/
https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-wpf-and-winforms/ https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-wpf-and-winforms/
https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-part-2/ https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-part-2/
https://blogs.msdn.microsoft.com/adamroot/2008/02/02/dragdroplib-cs/ https://blogs.msdn.microsoft.com/adamroot/2008/02/02/dragdroplib-cs/
https://www.codeproject.com/reference/1091137/windows-clipboard-formats https://www.codeproject.com/reference/1091137/windows-clipboard-formats
http://dlaa.me/blog/post/9923072 http://dlaa.me/blog/post/9923072
使用 IStream 拖放虚拟文件 https://stackoverflow.com/questions/1187444/drag-and-drop-virtual-files-using-istream
http://www.ookii.org/Blog/opening_files_via_idroptarget_in_net http://www.ookii.org/Blog/opening_files_via_idroptarget_in_net
https://www.codeproject.com/Articles/28209/Outlook-Drag-and-Drop-in-C https://www.codeproject.com/Articles/28209/Outlook-Drag-and-Drop-in-C