| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Runtime.InteropServices.ComTypes;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.Text;
- using Avalonia.Input.DragDrop;
- using Avalonia.Win32.Interop;
- using IDataObject = System.Runtime.InteropServices.ComTypes.IDataObject;
- namespace Avalonia.Win32
- {
- class OleDataObject : Avalonia.Input.DragDrop.IDataObject
- {
- private IDataObject _wrapped;
- public OleDataObject(IDataObject wrapped)
- {
- _wrapped = wrapped;
- }
- public bool Contains(string dataFormat)
- {
- return GetDataFormatsCore().Any(df => StringComparer.OrdinalIgnoreCase.Equals(df, dataFormat));
- }
- public IEnumerable<string> GetDataFormats()
- {
- return GetDataFormatsCore().Distinct();
- }
- public string GetText()
- {
- return GetDataFromOleHGLOBAL(DataFormats.Text, DVASPECT.DVASPECT_CONTENT) as string;
- }
- public IEnumerable<string> GetFileNames()
- {
- return GetDataFromOleHGLOBAL(DataFormats.FileNames, DVASPECT.DVASPECT_CONTENT) as IEnumerable<string>;
- }
- public object Get(string dataFormat)
- {
- return GetDataFromOleHGLOBAL(dataFormat, DVASPECT.DVASPECT_CONTENT);
- }
- private object GetDataFromOleHGLOBAL(string format, DVASPECT aspect)
- {
- FORMATETC formatEtc = new FORMATETC();
- formatEtc.cfFormat = ClipboardFormats.GetFormat(format);
- formatEtc.dwAspect = aspect;
- formatEtc.lindex = -1;
- formatEtc.tymed = TYMED.TYMED_HGLOBAL;
- if (_wrapped.QueryGetData(ref formatEtc) == 0)
- {
- _wrapped.GetData(ref formatEtc, out STGMEDIUM medium);
- try
- {
- if (medium.unionmember != IntPtr.Zero && medium.tymed == TYMED.TYMED_HGLOBAL)
- {
- if (format == DataFormats.Text)
- return ReadStringFromHGlobal(medium.unionmember);
- if (format == DataFormats.FileNames)
- return ReadFileNamesFromHGlobal(medium.unionmember);
- byte[] data = ReadBytesFromHGlobal(medium.unionmember);
- if (IsSerializedObject(data))
- {
- using (var ms = new MemoryStream(data))
- {
- ms.Position = DataObject.SerializedObjectGUID.Length;
- BinaryFormatter binaryFormatter = new BinaryFormatter();
- return binaryFormatter.Deserialize(ms);
- }
- }
- return data;
- }
- }
- finally
- {
- UnmanagedMethods.ReleaseStgMedium(ref medium);
- }
- }
- return null;
- }
- private bool IsSerializedObject(byte[] data)
- {
- if (data.Length < DataObject.SerializedObjectGUID.Length)
- return false;
- for (int i = 0; i < DataObject.SerializedObjectGUID.Length; i++)
- if (data[i] != DataObject.SerializedObjectGUID[i])
- return false;
- return true;
- }
- private static IEnumerable<string> ReadFileNamesFromHGlobal(IntPtr hGlobal)
- {
- List<string> files = new List<string>();
- int fileCount = UnmanagedMethods.DragQueryFile(hGlobal, -1, null, 0);
- if (fileCount > 0)
- {
- for (int i = 0; i < fileCount; i++)
- {
- int pathLen = UnmanagedMethods.DragQueryFile(hGlobal, i, null, 0);
- StringBuilder sb = new StringBuilder(pathLen+1);
- if (UnmanagedMethods.DragQueryFile(hGlobal, i, sb, sb.Capacity) == pathLen)
- {
- files.Add(sb.ToString());
- }
- }
- }
- return files;
- }
- private static string ReadStringFromHGlobal(IntPtr hGlobal)
- {
- IntPtr ptr = UnmanagedMethods.GlobalLock(hGlobal);
- try
- {
- return Marshal.PtrToStringAuto(ptr);
- }
- finally
- {
- UnmanagedMethods.GlobalUnlock(hGlobal);
- }
- }
- private static byte[] ReadBytesFromHGlobal(IntPtr hGlobal)
- {
- IntPtr source = UnmanagedMethods.GlobalLock(hGlobal);
- try
- {
- int size = (int)UnmanagedMethods.GlobalSize(hGlobal).ToInt64();
- byte[] data = new byte[size];
- Marshal.Copy(source, data, 0, size);
- return data;
- }
- finally
- {
- UnmanagedMethods.GlobalUnlock(hGlobal);
- }
- }
- private IEnumerable<string> GetDataFormatsCore()
- {
- var enumFormat = _wrapped.EnumFormatEtc(DATADIR.DATADIR_GET);
- if (enumFormat != null)
- {
- enumFormat.Reset();
- FORMATETC[] formats = new FORMATETC[1];
- int[] fetched = { 1 };
- while (fetched[0] > 0)
- {
- fetched[0] = 0;
- if (enumFormat.Next(1, formats, fetched) == 0 && fetched[0] > 0)
- {
- if (formats[0].ptd != IntPtr.Zero)
- Marshal.FreeCoTaskMem(formats[0].ptd);
-
- yield return ClipboardFormats.GetFormat(formats[0].cfFormat);
- }
- }
- }
- }
- }
- }
|