I found one example on late-rendering on the web (don't know on which page) and was able to modify it that way, to support large-Files (I tested it with a 250 MB file) and IStream.
This example is written in for .NET 2.0 and far from being perfect but hopefully it will give some hints.
I will post the code of this two files
File 1 (Example.cs is 63 lines of code), File 2(VirtualFileDataObject.cs is 1125 lines of code)
// Example.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Delay;
using System.IO;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
namespace DOExample
{
public partial class Example : Form
{
public Example()
{
InitializeComponent();
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
VirtualFileDataObject vfdo = new VirtualFileDataObject();
vfdo.IsAsynchronous = true;
vfdo.PreferredDropEffect = DragDropEffects.Copy;
VirtualFileDataObject.FileDescriptor fileDecriptor1 = new VirtualFileDataObject.FileDescriptor();
List<VirtualFileDataObject.FileDescriptor> fileDescriptors = new List<VirtualFileDataObject.FileDescriptor>();
string filePath = @"C:\Program Files (x86)\VMware\VMware Workstation\pkg\Tools.cab";
FileInfo fi = new FileInfo(filePath);
fileDecriptor1.Name = fi.Name;
fileDecriptor1.Length = fi.Length;
fileDecriptor1.ChangeTimeUtc = fi.LastWriteTimeUtc;
fileDecriptor1.ExtraInfo = fi.FullName;
fileDecriptor1.StreamContents = new VirtualFileDataObject.MyAction<Delay.VirtualFileDataObject.Tuple<Stream,string>>(GetFileData);
fileDescriptors.Add(fileDecriptor1);
vfdo.SetData(fileDescriptors);
vfdo.PreferredDropEffect = DragDropEffects.Copy;
button1.DoDragDrop(vfdo, DragDropEffects.Copy);
}
public void GetFileData(Delay.VirtualFileDataObject.Tuple<Stream, string> tuple)
{
using (FileStream sourceStream = new FileStream(tuple.Item2, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[1024 * 1024];
while (true)
{
int read = sourceStream.Read(buffer, 0, buffer.Length);
if (read <= 0)
break;
tuple.Item1.Write(buffer, 0, read);
}
}
}
}
}
------------------------------------------------------------------------------------------
// VirtualFileDataObject.cs
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;
using System.Collections.Specialized;
namespace Delay
{
public class VirtualFileDataObject : System.Runtime.InteropServices.ComTypes.IDataObject, IAsyncOperation
{
public bool IsAsynchronous { get; set; }
private static short FILECONTENTS = (short)(DataFormats.GetFormat(NativeMethods.CFSTR_FILECONTENTS).Id);
private static short FILEDESCRIPTORW = (short)(DataFormats.GetFormat(NativeMethods.CFSTR_FILEDESCRIPTORW).Id);
private static short PASTESUCCEEDED = (short)(DataFormats.GetFormat(NativeMethods.CFSTR_PASTESUCCEEDED).Id);
private static short PERFORMEDDROPEFFECT = (short)(DataFormats.GetFormat(NativeMethods.CFSTR_PERFORMEDDROPEFFECT).Id);
private static short PREFERREDDROPEFFECT = (short)(DataFormats.GetFormat(NativeMethods.CFSTR_PREFERREDDROPEFFECT).Id);
private List<DataObject> _dataObjects = new List<DataObject>();
private bool _inOperation;
private Action<VirtualFileDataObject> _startAction;
private Action<VirtualFileDataObject> _endAction;
public VirtualFileDataObject()
{
IsAsynchronous = true;
}
public VirtualFileDataObject(Action<VirtualFileDataObject> startAction, Action<VirtualFileDataObject> endAction)
: this()
{
_startAction = startAction;
_endAction = endAction;
}
#region IDataObject Members
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")]
int System.Runtime.InteropServices.ComTypes.IDataObject.DAdvise(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink adviseSink, out int connection)
{
Marshal.ThrowExceptionForHR(NativeMethods.OLE_E_ADVISENOTSUPPORTED);
throw new NotImplementedException();
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")]
void System.Runtime.InteropServices.ComTypes.IDataObject.DUnadvise(int connection)
{
Marshal.ThrowExceptionForHR(NativeMethods.OLE_E_ADVISENOTSUPPORTED);
throw new NotImplementedException();
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")]
int System.Runtime.InteropServices.ComTypes.IDataObject.EnumDAdvise(out IEnumSTATDATA enumAdvise)
{
Marshal.ThrowExceptionForHR(NativeMethods.OLE_E_ADVISENOTSUPPORTED);
throw new NotImplementedException();
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")]
IEnumFORMATETC System.Runtime.InteropServices.ComTypes.IDataObject.EnumFormatEtc(DATADIR direction)
{
if (direction == DATADIR.DATADIR_GET)
{
if (0 == _dataObjects.Count)
{
throw new InvalidOperationException("VirtualFileDataObject requires at least one data object to enumerate.");
}
IEnumFORMATETC enumerator;
List<FORMATETC> formatetcs = new List<FORMATETC>(_dataObjects.Count);
foreach (DataObject d in _dataObjects)
{
formatetcs.Add(d.FORMATETC);
}
if (NativeMethods.SUCCEEDED(NativeMethods.SHCreateStdEnumFmtEtc((uint)(_dataObjects.Count), formatetcs.ToArray(), out enumerator)))
{
return enumerator;
}
Marshal.ThrowExceptionForHR(NativeMethods.E_FAIL);
}
throw new NotImplementedException();
}
int System.Runtime.InteropServices.ComTypes.IDataObject.GetCanonicalFormatEtc(ref FORMATETC formatIn, out FORMATETC formatOut)
{
throw new NotImplementedException();
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")]
void System.Runtime.InteropServices.ComTypes.IDataObject.GetData(ref FORMATETC format, out STGMEDIUM medium)
{
medium = new STGMEDIUM();
var hr = ((System.Runtime.InteropServices.ComTypes.IDataObject)this).QueryGetData(ref format);
if (NativeMethods.SUCCEEDED(hr))
{
DataObject dataObject = null;
foreach (DataObject d in _dataObjects)
{
if ((d.FORMATETC.cfFormat == format.cfFormat) &&
(d.FORMATETC.dwAspect == format.dwAspect) &&
(0 != (d.FORMATETC.tymed & format.tymed) &&
(d.FORMATETC.lindex == format.lindex)))
{
dataObject = d;
break;
}
}
if (dataObject != null)
{
if (!IsAsynchronous && (FILEDESCRIPTORW == dataObject.FORMATETC.cfFormat) && !_inOperation)
{
_inOperation = true;
if (null != _startAction)
{
_startAction(this);
}
}
medium.tymed = dataObject.FORMATETC.tymed;
var result = dataObject.GetData();
hr = result.Item2;
if (NativeMethods.SUCCEEDED(hr))
{
medium.unionmember = result.Item1;
}
}
else
{
hr = NativeMethods.DV_E_FORMATETC;
}
}
if (!NativeMethods.SUCCEEDED(hr))
{
Marshal.ThrowExceptionForHR(hr);
}
}
void System.Runtime.InteropServices.ComTypes.IDataObject.GetDataHere(ref FORMATETC format, ref STGMEDIUM medium)
{
throw new NotImplementedException();
}
int System.Runtime.InteropServices.ComTypes.IDataObject.QueryGetData(ref FORMATETC format)
{
List<DataObject> formatMatches = new List<DataObject>();
foreach (DataObject d in _dataObjects)
{
if (d.FORMATETC.cfFormat == format.cfFormat)
{
formatMatches.Add(d);
}
}
if (formatMatches.Count == 0)
{
return NativeMethods.DV_E_FORMATETC;
}
List<DataObject> tymedMatches = new List<DataObject>();
foreach (DataObject d in formatMatches)
{
if ((d.FORMATETC.tymed & format.tymed) != 0)
{
tymedMatches.Add(d);
}
}
if (tymedMatches.Count == 0)
{
return NativeMethods.DV_E_TYMED;
}
List<DataObject> aspectMatches = new List<DataObject>();
foreach (DataObject d in tymedMatches)
{
if (d.FORMATETC.dwAspect == format.dwAspect)
{
aspectMatches.Add(d);
}
}
if (aspectMatches.Count == 0)
{
return NativeMethods.DV_E_DVASPECT;
}
return NativeMethods.S_OK;
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")]
void System.Runtime.InteropServices.ComTypes.IDataObject.SetData(ref FORMATETC formatIn, ref STGMEDIUM medium, bool release)
{
var handled = false;
if ((formatIn.dwAspect == DVASPECT.DVASPECT_CONTENT) &&
(formatIn.tymed == TYMED.TYMED_HGLOBAL) &&
(medium.tymed == formatIn.tymed))
{
var ptr = NativeMethods.GlobalLock(medium.unionmember);
if (IntPtr.Zero != ptr)
{
try
{
var length = NativeMethods.GlobalSize(ptr).ToInt32();
byte[] data = new byte[length];
Marshal.Copy(ptr, data, 0, length);
SetData(formatIn.cfFormat, data);
handled = true;
}
finally
{
NativeMethods.GlobalUnlock(medium.unionmember);
}
}
if (release)
{
Marshal.FreeHGlobal(medium.unionmember);
}
}
if (!IsAsynchronous && (PERFORMEDDROPEFFECT == formatIn.cfFormat) && _inOperation)
{
if (null != _endAction)
{
_endAction(this);
}
_inOperation = false;
}
if (!handled)
{
throw new NotImplementedException();
}
}
#endregion
public void SetData(StringCollection fileDropList)
{
DataObject dataObj = new DataObject();
}
public void SetData(short dataFormat, byte[] data)
{
_dataObjects.Add(
new DataObject
{
FORMATETC = new FORMATETC
{
cfFormat = dataFormat,
ptd = IntPtr.Zero,
dwAspect = DVASPECT.DVASPECT_CONTENT,
lindex = -1,
tymed = TYMED.TYMED_HGLOBAL
},
GetData = () =>
{
var dataArray = data;
var ptr = Marshal.AllocHGlobal(dataArray.Length);
Marshal.Copy(dataArray, 0, ptr, dataArray.Length);
return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK);
},
});
}
public void SetData(short dataFormat, int index, MyAction<Tuple<Stream,string>> streamAndId, FileDescriptor fileDescriptor)
{
_dataObjects.Add(
new DataObject
{
FORMATETC = new FORMATETC
{
cfFormat = dataFormat,
ptd = IntPtr.Zero,
dwAspect = DVASPECT.DVASPECT_CONTENT,
lindex = index,
tymed = TYMED.TYMED_ISTREAM
},
GetData = () =>
{
var ptr = IntPtr.Zero;
var iStream = NativeMethods.CreateStreamOnHGlobal(IntPtr.Zero, true);
if (streamAndId != null)
{
using (var stream = new IStreamWrapper(iStream))
{
streamAndId.Invoke(new Tuple<Stream,string>(stream, fileDescriptor.ExtraInfo));
}
}
ptr = Marshal.GetComInterfaceForObject(iStream, typeof(IStream));
Marshal.ReleaseComObject(iStream);
return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK);
},
});
}
public void SetData(List<FileDescriptor> fileDescriptors)
{
var bytes = new List<byte>();
bytes.AddRange(StructureBytes(new NativeMethods.FILEGROUPDESCRIPTOR { cItems = (uint)(fileDescriptors.Count) }));
foreach (var fileDescriptor in fileDescriptors)
{
var FILEDESCRIPTOR = new NativeMethods.FILEDESCRIPTOR
{
cFileName = fileDescriptor.Name,
};
if (fileDescriptor.ChangeTimeUtc.HasValue)
{
FILEDESCRIPTOR.dwFlags |= NativeMethods.FD_CREATETIME | NativeMethods.FD_WRITESTIME;
var changeTime = fileDescriptor.ChangeTimeUtc.Value.ToLocalTime().ToFileTime();
var changeTimeFileTime = new System.Runtime.InteropServices.ComTypes.FILETIME
{
dwLowDateTime = (int)(changeTime & 0xffffffff),
dwHighDateTime = (int)(changeTime >> 32),
};
FILEDESCRIPTOR.ftLastWriteTime = changeTimeFileTime;
FILEDESCRIPTOR.ftCreationTime = changeTimeFileTime;
}
if (fileDescriptor.Length.HasValue)
{
FILEDESCRIPTOR.dwFlags |= NativeMethods.FD_FILESIZE;
FILEDESCRIPTOR.nFileSizeLow = (uint)(fileDescriptor.Length & 0xffffffff);
FILEDESCRIPTOR.nFileSizeHigh = (uint)(fileDescriptor.Length >> 32);
}
bytes.AddRange(StructureBytes(FILEDESCRIPTOR));
}
SetData(FILEDESCRIPTORW, bytes.ToArray());
var index = 0;
foreach (var fileDescriptor in fileDescriptors)
{
SetData(FILECONTENTS, index, fileDescriptor.StreamContents, fileDescriptor);
index++;
}
}
public DragDropEffects? PasteSucceeded
{
get { return GetDropEffect(PASTESUCCEEDED); }
set
{
List<byte> data = new List<byte>(BitConverter.GetBytes((UInt32)value));
SetData(PASTESUCCEEDED, data.ToArray());
}
}
public DragDropEffects? PerformedDropEffect
{
get { return GetDropEffect(PERFORMEDDROPEFFECT); }
set
{
List<byte> data = new List<byte>(BitConverter.GetBytes((UInt32)value));
SetData(PERFORMEDDROPEFFECT, data.ToArray());
}
}
public DragDropEffects? PreferredDropEffect
{
get { return GetDropEffect(PREFERREDDROPEFFECT); }
set
{
List<byte> data = new List<byte>(BitConverter.GetBytes((UInt32)value));
SetData(PREFERREDDROPEFFECT, data.ToArray());
}
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")]
private DragDropEffects? GetDropEffect(short format)
{
DataObject dataObject = null;
foreach (DataObject d in _dataObjects)
{
if ((format == d.FORMATETC.cfFormat) &&
(DVASPECT.DVASPECT_CONTENT == d.FORMATETC.dwAspect) &&
(TYMED.TYMED_HGLOBAL == d.FORMATETC.tymed))
{
dataObject = d;
}
}
if (null != dataObject)
{
var result = dataObject.GetData();
if (NativeMethods.SUCCEEDED(result.Item2))
{
var ptr = NativeMethods.GlobalLock(result.Item1);
if (IntPtr.Zero != ptr)
{
try
{
var length = NativeMethods.GlobalSize(ptr).ToInt32();
if (4 == length)
{
var data = new byte[length];
Marshal.Copy(ptr, data, 0, length);
return (DragDropEffects)(BitConverter.ToUInt32(data, 0));
}
}
finally
{
NativeMethods.GlobalUnlock(result.Item1);
}
}
}
}
return null;
}
#region IAsyncOperation Members
void IAsyncOperation.SetAsyncMode(int fDoOpAsync)
{
IsAsynchronous = !(NativeMethods.VARIANT_FALSE == fDoOpAsync);
}
void IAsyncOperation.GetAsyncMode(out int pfIsOpAsync)
{
pfIsOpAsync = IsAsynchronous ? NativeMethods.VARIANT_TRUE : NativeMethods.VARIANT_FALSE;
}
void IAsyncOperation.StartOperation(IBindCtx pbcReserved)
{
_inOperation = true;
if (null != _startAction)
{
_startAction(this);
}
}
void IAsyncOperation.InOperation(out int pfInAsyncOp)
{
pfInAsyncOp = _inOperation ? NativeMethods.VARIANT_TRUE : NativeMethods.VARIANT_FALSE;
}
void IAsyncOperation.EndOperation(int hResult, IBindCtx pbcReserved, uint dwEffects)
{
if (null != _endAction)
{
_endAction(this);
}
_inOperation = false;
}
#endregion
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")]
private static IEnumerable<byte> StructureBytes(object source)
{
var size = Marshal.SizeOf(source.GetType());
var ptr = Marshal.AllocHGlobal(size);
var bytes = new byte[size];
try
{
Marshal.StructureToPtr(source, ptr, false);
Marshal.Copy(ptr, bytes, 0, size);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return bytes;
}
public delegate void MyAction<T>(T obj);
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Justification = "Deliberate to provide obvious coupling.")]
public class FileDescriptor
{
public string Name { get; set; }
public Int64? Length { get; set; }
public DateTime? ChangeTimeUtc { get; set; }
public MyAction<Tuple<Stream, string>> StreamContents { get; set; }
public string ExtraInfo { get; set; }
}
private class DataObject
{
public FORMATETC FORMATETC { get; set; }
public Func<Tuple<IntPtr, int>> GetData { get; set; }
}
public class Tuple<T1, T2>
{
public T1 Item1 { get; private set; }
public T2 Item2 { get; private set; }
public Tuple(T1 item1, T2 item2)
{
Item1 = item1;
Item2 = item2;
}
}
public delegate TResult Func<TResult>();
private class IStreamWrapper : Stream
{
private IStream _iStream;
public IStreamWrapper(IStream iStream)
{
_iStream = iStream;
}
public override bool CanRead
{
get { return false; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return true; }
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Length
{
get { throw new NotImplementedException(); }
}
public override long Position
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
if (offset == 0)
{
_iStream.Write(buffer, count, IntPtr.Zero);
}
else
{
ArraySegment<byte> buf = new ArraySegment<byte>(buffer, offset, count);
_iStream.Write(buf.Array, count, IntPtr.Zero);
}
}
}
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "dragSource", Justification = "Parameter is present so the signature matches that of System.Windows.DragDrop.DoDragDrop.")]
public static DragDropEffects DoDragDrop(object dragSource, System.Runtime.InteropServices.ComTypes.IDataObject dataObject, DragDropEffects allowedEffects)
{
int[] finalEffect = new int[1];
try
{
NativeMethods.DoDragDrop(dataObject, new DropSource(), (int)allowedEffects, finalEffect);
}
finally
{
var virtualFileDataObject = dataObject as VirtualFileDataObject;
if ((null != virtualFileDataObject) && !virtualFileDataObject.IsAsynchronous && virtualFileDataObject._inOperation)
{
if (null != virtualFileDataObject._endAction)
{
virtualFileDataObject._endAction(virtualFileDataObject);
}
virtualFileDataObject._inOperation = false;
}
}
return (DragDropEffects)(finalEffect[0]);
}
private class DropSource : NativeMethods.IDropSource
{
public int QueryContinueDrag(int fEscapePressed, uint grfKeyState)
{
var escapePressed = (0 != fEscapePressed);
var keyStates = (DragDropKeyStates)grfKeyState;
if (escapePressed)
{
return NativeMethods.DRAGDROP_S_CANCEL;
}
else if (DragDropKeyStates.None == (keyStates & DragDropKeyStates.LeftMouseButton))
{
return NativeMethods.DRAGDROP_S_DROP;
}
return NativeMethods.S_OK;
}
public int GiveFeedback(uint dwEffect)
{
return NativeMethods.DRAGDROP_S_USEDEFAULTCURSORS;
}
}
public static class NativeMethods
{
public const int DRAGDROP_S_DROP = 0x00040100;
public const int DRAGDROP_S_CANCEL = 0x00040101;
public const int DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102;
public const int DV_E_DVASPECT = -2147221397;
public const int DV_E_FORMATETC = -2147221404;
public const int DV_E_TYMED = -2147221399;
public const int E_FAIL = -2147467259;
public const uint FD_CREATETIME = 0x00000008;
public const uint FD_WRITESTIME = 0x00000020;
public const uint FD_FILESIZE = 0x00000040;
public const int OLE_E_ADVISENOTSUPPORTED = -2147221501;
public const int S_OK = 0;
public const int S_FALSE = 1;
public const int VARIANT_FALSE = 0;
public const int VARIANT_TRUE = -1;
public const string CFSTR_FILECONTENTS = "FileContents";
public const string CFSTR_FILEDESCRIPTORW = "FileGroupDescriptorW";
public const string CFSTR_PASTESUCCEEDED = "Paste Succeeded";
public const string CFSTR_PERFORMEDDROPEFFECT = "Performed DropEffect";
public const string CFSTR_PREFERREDDROPEFFECT = "Preferred DropEffect";
[SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "Structure exists for interop.")]
[StructLayout(LayoutKind.Sequential)]
public struct FILEGROUPDESCRIPTOR
{
public UInt32 cItems;
}
[SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "Structure exists for interop.")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct FILEDESCRIPTOR
{
public UInt32 dwFlags;
public Guid clsid;
public Int32 sizelcx;
public Int32 sizelcy;
public Int32 pointlx;
public Int32 pointly;
public UInt32 dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public UInt32 nFileSizeHigh;
public UInt32 nFileSizeLow;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
}
[SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "Structure exists for interop.")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct POINT
{
public Int32 X;
public Int32 Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
[SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "Structure exists for interop.")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DROPFILES
{
public int pFiles;
public POINT point;
public bool fNC;
public bool fWide;
}
[ComImport]
[Guid("00000121-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDropSource
{
[PreserveSig]
int QueryContinueDrag(int fEscapePressed, uint grfKeyState);
[PreserveSig]
int GiveFeedback(uint dwEffect);
}
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "Win32 API.")]
[DllImport("shell32.dll")]
public static extern int SHCreateStdEnumFmtEtc(uint cfmt, FORMATETC[] afmt, out IEnumFORMATETC ppenumFormatEtc);
[return: MarshalAs(UnmanagedType.Interface)]
[DllImport("ole32.dll", PreserveSig = false)]
public static extern IStream CreateStreamOnHGlobal(IntPtr hGlobal, [MarshalAs(UnmanagedType.Bool)] bool fDeleteOnRelease);
[DllImport("ole32.dll", CharSet = CharSet.Auto, ExactSpelling = true, PreserveSig = false)]
public static extern void DoDragDrop(System.Runtime.InteropServices.ComTypes.IDataObject dataObject, IDropSource dropSource, int allowedEffects, int[] finalEffect);
[DllImport("kernel32.dll")]
public static extern IntPtr GlobalLock(IntPtr hMem);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll")]
public static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("kernel32.dll")]
public static extern IntPtr GlobalSize(IntPtr handle);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam,
IntPtr lParam);
public const uint WM_DROPFILES = 0x0233;
public static bool SUCCEEDED(int hr)
{
return (0 <= hr);
}
}
}
[ComImport]
[Guid("3D8B0590-F691-11d2-8EA9-006097DF5BD4")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAsyncOperation
{
void SetAsyncMode([In] Int32 fDoOpAsync);
void GetAsyncMode([Out] out Int32 pfIsOpAsync);
void StartOperation([In] IBindCtx pbcReserved);
void InOperation([Out] out Int32 pfInAsyncOp);
void EndOperation([In] Int32 hResult, [In] IBindCtx pbcReserved, [In] UInt32 dwEffects);
}
[Flags]
public enum DragDropKeyStates
{
None = 0,
LeftMouseButton = 1,
RightMouseButton = 2,
ShiftKey = 4,
ControlKey = 8,
MiddleMouseButton = 16,
AltKey = 32,
}
}
|