/// <summary> /// Update the displayed drag drop effects /// </summary> /// <param name="effects">Drag & Drop effect to be applied</param> /// <param name="type">DropImageType effect to be used</param> /// <param name="format">format to be displayed on the icon</param> /// <param name="destination">drop destination name</param> public void UpdateEffects(DragDropEffects effects, DropImageType type, string format, string destination) { Effects = effects; if (ComData != null) { // Size of insert is limited to 259 if (destination != null && destination.Length > 259) { destination = destination.Substring(255) + "..."; } // C# format to C format format = format?.Replace("{0}", "%1"); // All these steps are required to update the Drop-description ComDataObject.SetDropDescription(ComData, type, format, destination); ComDataObject.InvalidateDragImage(ComData); UpdatePosition(); // force a DDHelper.DragOver call } }
/// <summary> /// Gets managed data from a clipboard DataObject. /// </summary> /// <param name="dataObject">The DataObject to obtain the data from.</param> /// <param name="format">The format for which to get the data in.</param> /// <returns>The data object instance.</returns> public static object GetManagedData(ComDataObject dataObject, string format) { FillFormatETC(format, TYMED.TYMED_HGLOBAL, out FORMATETC formatETC); // Get the data as a stream dataObject.GetData(ref formatETC, out STGMEDIUM medium); IStream nativeStream; try { int hr = CreateStreamOnHGlobal(medium.unionmember, true, out nativeStream); if (hr != 0) { return(null); } } finally { ReleaseStgMedium(ref medium); } // Convert the native stream to a managed stream nativeStream.Stat(out System.Runtime.InteropServices.ComTypes.STATSTG statstg, 0); if (statstg.cbSize > int.MaxValue) { throw new NotSupportedException(); } byte[] buf = new byte[statstg.cbSize]; nativeStream.Read(buf, (int)statstg.cbSize, IntPtr.Zero); MemoryStream dataStream = new MemoryStream(buf); // Check for our stamp int sizeOfGuid = Marshal.SizeOf(typeof(Guid)); byte[] guidBytes = new byte[sizeOfGuid]; if (dataStream.Length >= sizeOfGuid) { if (sizeOfGuid == dataStream.Read(guidBytes, 0, sizeOfGuid)) { Guid guid = new Guid(guidBytes); if (ManagedDataStamp.Equals(guid)) { // Stamp matched, so deserialize BinaryFormatter formatter = new BinaryFormatter(); Type dataType = (Type)formatter.Deserialize(dataStream); object data2 = formatter.Deserialize(dataStream); if (data2.GetType() == dataType) { return(data2); } else if (data2 is string) { return(ConvertDataFromString((string)data2, dataType)); } else { return(null); } } } } // Stamp didn't match... attempt to reset the seek pointer if (dataStream.CanSeek) { dataStream.Position = 0; } return(null); }
// ---------------------------------------------------------------------------------------------- #region Impelmentation /// <summary> /// Create or handle a system-style Drag & Drop icon /// </summary> /// <param name="element">Element to represent or where the Drag & Drop operation occurs</param> /// <param name="dataObject">Data Object dragged during Drag & Drop</param> /// <param name="effects">Drag & Drop effects</param> /// <param name="scale">Scale of the element representation when creating icon (1.0: unchanged)</param> /// <param name="create">create the icon representation from the element, otherwise tries to continue the existing Drag & Drop from the dataObject</param> public DragSystemIcon(FrameworkElement element, IDataObject dataObject, DragDropEffects effects, double scale, bool create) { // retrieve window handle var window = PresentationSource.FromVisual(element).RootVisual; var hwnd = ((HwndSource)PresentationSource.FromVisual(window)).Handle; if (create) { Element = element; if (element is ContentPresenter) { element = WPF.FindFirstChild <FrameworkElement>(element); } // Convert the visual element to a Bitmap var dpi = 96 * scale; var renderbmp = WPF.ProduceImageSourceForVisual(element, dpi, dpi); // Retrieve renderbmp pixel array const int pixsize = 4; // Pbgra32 implies 4 bytes per pixels int stride = renderbmp.PixelWidth * pixsize; byte[] pix = new byte[renderbmp.PixelHeight * stride]; renderbmp.CopyPixels(pix, stride, 0); for (int i = 3; i < pix.Length; i += pixsize) { if (pix[i] == 0) { // Convert fully transparent pixels to Magenta (this will become transparent in ShDragImage) pix[i - 0] = 0xFF; // A pix[i - 1] = 0xFF; // R pix[i - 2] = 0x00; // G pix[i - 3] = 0xFF; // B } else if (pix[i] == 0xFF && pix[i - 1] == 0xFF && pix[i - 2] == 0x00 && pix[i - 3] == 0xFF) { // change Magenta pixels to *almost* magenta, to avoid changing these to transparent in ShDragImage pix[i - 2] = 0x01; } } // Convert pixel array to BitmapSource var bitmapsrc = BitmapSource.Create(renderbmp.PixelWidth, renderbmp.PixelHeight, 96, 96, PixelFormats.Bgra32, null, pix, stride); // Convert BitmapSource to Bitmap System.Drawing.Bitmap bitmap; using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) { var encoder = new BmpBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bitmapsrc)); encoder.Save(stream); bitmap = new System.Drawing.Bitmap(stream); } //LimeMsg.Debug("ClipDragDrop DragSystemIcon: {0}", bitmap.GetPixel(0, 0)); // Compute destination size WPF.Win32Size size; size.cx = (int)(renderbmp.PixelWidth * scale); size.cy = (int)(renderbmp.PixelHeight * scale); WPF.SysPoint wpt; wpt.x = size.cx / 2; wpt.y = size.cy / 2; ShDragImage shdi = new ShDragImage { sizeDragImage = size, ptOffset = wpt, hbmpDragImage = bitmap.GetHbitmap(), crColorKey = System.Drawing.Color.Magenta.ToArgb() }; var sourceHelper = (IDragSourceHelper2) new DragDropHelper(); sourceHelper.SetFlags(1); // Enable Drop description // Not quite right var com = new ComDataObject(); dataObject = new DataObject(com); sourceHelper.InitializeFromBitmap(ref shdi, (System.Runtime.InteropServices.ComTypes.IDataObject)dataObject); } else { Element = null; } ComData = dataObject; Effects = effects; Scale = scale; // Create the System Drag Helper and show it at the mouse location WPF.GetCursorPos(out WPF.SysPoint spos); DDHelper = (IDropTargetHelper) new DragDropHelper(); DDHelper.DragEnter(hwnd, (System.Runtime.InteropServices.ComTypes.IDataObject)dataObject, ref spos, Effects); }