示例#1
0
        /// <summary>
        /// Constructor of the FrameworkElement representation, which can be moved anywhere on the screen
        /// </summary>
        /// <param name="element">Element to create an avatar from</param>
        /// <param name="scale">Scale of the represented avatar compared to its source (default: 1.0: equal size)</param>
        /// <param name="opacity">Opacity of the represented avatar compared to its source (default: 1.0)</param>
        public FreeFrameworkElementAvatar(FrameworkElement element, double scale = 1.0, double opacity = 1.0)
        {
            if (element.GetType() == typeof(ContentPresenter))
            {
                element = WPF.FindFirstChild <FrameworkElement>(element);
            }

            // Create the image
            Image = new Image()
            {
                // Icon Image
                Style   = new Style(typeof(Image)),
                Source  = WPF.ProduceImageSourceForVisual(element),
                Opacity = opacity,
            };

            // Create the visual
            DragIcon = new Popup()
            {
                AllowsTransparency = true,
                PopupAnimation     = PopupAnimation.None,
                Placement          = PlacementMode.Absolute,
                Width  = element.ActualWidth * scale,
                Height = element.ActualHeight * scale,
                Child  = Image
            };
        }
示例#2
0
        /// <summary>
        /// Bring the avatar at a given screen position
        /// </summary>
        /// <param name="position">screen position</param>
        public void GotoPosition(Point position)
        {
            if (DragIcon != null)
            {
                if (!DragIcon.IsOpen)
                {
                    DragIcon.IsOpen = true;

                    // Make the icon transparent to the mouse. Unfortunatly, this code
                    // is sytem dependent. Alternative is to change the following icon position
                    // to not be under the the mouse (remove the offset for example).
                    WPF.SetWindowExTransparent(DragIcon.Child);
                }

                // Icon position with respect to mouse position.
                // Remove the Y offset if SetWindowExTransparent is not available on the system.
                DragIcon.HorizontalOffset = position.X - DragIcon.Width / 2.0;
                DragIcon.VerticalOffset   = position.Y - DragIcon.Height / 2.0;
            }
        }
示例#3
0
        // ----------------------------------------------------------------------------------------------
        #region Class functions


        private static void TargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var wxthis = (ItemsControl)d;

            if (e.OldValue is IItemsRangeInfo rinfo)
            {
                rinfo.Close();
            }

            var enable = e.NewValue is IItemsRangeInfo || e.NewValue is ISelectionInfo;

            if (enable)
            {
                // Lazy declaration of Timer
                if (Timer == null)
                {
                    Timer       = new DispatcherTimer();
                    Timer.Tick += OnTimerElapsed;
                }

                wxthis.Loaded   += OnLoaded;
                wxthis.Unloaded += OnUnloaded;
            }
            else
            {
                wxthis.Loaded   -= OnLoaded;
                wxthis.Unloaded -= OnUnloaded;
            }

            ScrollViewer wxscroll;

            if (wxthis is ListBox)
            {
                wxscroll = WPF.FindFirstChild <ScrollViewer>(wxthis);
            }
            else
            {
                wxscroll = WPF.FindFirstParent <ScrollViewer>(wxthis);
            }

            if (References == null)
            {
                References = new Dictionary <ScrollViewer, List <WeakReference> >();
            }

            if (References.TryGetValue(wxscroll, out var reflist))
            {
                // Remove dead references
                for (int i = 0; i < reflist.Count; i++)
                {
                    var wref = reflist[i];
                    if (!wref.IsAlive || wref.Target == wxthis)
                    {
                        reflist.RemoveAt(i);
                        i--;
                    }
                }
            }
            else if (enable)
            {
                reflist = new List <WeakReference>();
                References.Add(wxscroll, reflist);
            }

            if (enable)
            {
                reflist.Add(new WeakReference(wxthis));
                if (reflist.Count == 1)
                {
                    wxscroll.ScrollChanged += OnScrollChanged;
                }
            }
            else if (reflist == null || reflist.Count == 0)
            {
                wxscroll.ScrollChanged -= OnScrollChanged;
            }
        }
示例#4
0
        /// <summary>
        /// Update the virtualization of the scrollviewer in <see cref="Timer.Tag"/>
        /// </summary>
        /// <param name="sender"><see cref="Timer"/></param>
        /// <param name="e"></param>
        private static void OnTimerElapsed(object sender = null, EventArgs e = null)
        {
            LimeMsg.Debug("DataVirtualization OnTimerElapsed");

            Timer.Stop();
            var wxscroll = (ScrollViewer)Timer.Tag;

            Timer.Tag = null;

            var reflist = References[wxscroll];

            // TODO: optimize to take into account what was visible previously to not loop all over again
            foreach (var wref in reflist)
            {
                if (!wref.IsAlive || !(wref.Target is ItemsControl wxctrl))
                {
                    continue;
                }

                var itemgen = wxctrl.ItemContainerGenerator;
                var itemcnt = itemgen.Items.Count;

                int startSelected = -1;
                int endSelected   = -1;
                var rangeSelected = new List <ItemIndexRange>();

                int startVisible = -1;
                int endVisible   = -1;
                var rangeVisible = new List <ItemIndexRange>();

                for (int i = 0; i < itemcnt; i++)
                {
                    if (!(itemgen.ContainerFromIndex(i) is FrameworkElement wxitem))
                    {
                        continue;
                    }
                    if (wxitem.DataContext is IItemsRangeInfo)
                    {
                        // Detect selected items
                        if (wxitem.IsFocused)
                        {
                            if (startSelected == -1)
                            {
                                startSelected = i;
                            }
                            endSelected = i;
                        }
                        else if (Selector.GetIsSelected(wxitem))
                        {
                            if (startSelected == -1)
                            {
                                startSelected = i;
                            }
                            endSelected = i;
                        }
                        else if (startSelected != -1)
                        {
                            rangeSelected.Add(new ItemIndexRange(startSelected, (uint)(endSelected - startSelected + 1)));
                            startSelected = -1;
                        }

                        // Detect visible items
                        if (WPF.IsFullyOrPartiallyVisible(wxitem, wxscroll))
                        {
                            if (startVisible == -1)
                            {
                                startVisible = i;
                            }
                            endVisible = i;
                        }
                        else if (startVisible != -1)
                        {
                            rangeVisible.Add(new ItemIndexRange(startVisible, (uint)(endVisible - startVisible + 1)));
                            startVisible = -1;
                        }
                    }
                }

                var target = GetTarget(wxctrl);

                // TODO: handle selection


                if (target is IItemsRangeInfo rinfo)
                {
                    if (startVisible != -1)
                    {
                        rangeVisible.Add(new ItemIndexRange(startVisible, (uint)(endVisible - startVisible + 1)));
                        startVisible = -1;
                    }

                    if (rangeVisible.Count > 0)
                    {
                        rinfo.RangesChanged(rangeVisible[0], new ReadOnlyCollection <ItemIndexRange>(rangeVisible));
                    }
                }
            }
        }
示例#5
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);
        }