尝试从chrome实现拖放gmail附件

我一直在尝试将chrome中的gmail附件拖放到我的应用程序中。

可以将文件从电子邮件拖到桌面,然后在那里创建附件,所以我知道这一定是可能的。

我已经能够让它读取文件名,但是当我从数据对象中读取FileContents时,我得到一个带有文件链接的Internet快捷方式。

有人有过这个工作吗? 目前的代码是.txt文件的硬编码

示例项目可以从以下位置下载:

https://www.dropbox.com/s/jz4zde0mvgxzn1g/DragDropTest.zip?dl=0

我的主要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 dataDictionary = new Dictionary(); 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

使用VirtualFileDataObject使用IStream拖放大型虚拟文件

将大型虚拟文件从C#拖放到Windows资源管理器中

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://dlaa.me/blog/post/9923072

使用IStream拖放虚拟文件

https://blogs.msdn.microsoft.com/adamroot/2008/02/19/shell-style-drag-and-drop-in-net-wpf-and-winforms/

在我的.NET Windows窗体上实现Chrome的拖放操作

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-part-2/

https://blogs.msdn.microsoft.com/adamroot/2008/02/02/dragdroplib-cs/

https://www.codeproject.com/reference/1091137/windows-clipboard-formats

http://dlaa.me/blog/post/9923072

使用IStream拖放虚拟文件

http://www.ookii.org/Blog/opening_files_via_idroptarget_in_net

https://www.codeproject.com/Articles/28209/Outlook-Drag-and-Drop-in-C