예제 #1
0
        /// <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
            }
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        // ----------------------------------------------------------------------------------------------
        #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);
        }