diff --git a/Source/NDragDrop/DraggableVisualFeedback.xaml.cs b/Source/NDragDrop/DraggableVisualFeedback.xaml.cs index b6614a6..42f2d4a 100644 --- a/Source/NDragDrop/DraggableVisualFeedback.xaml.cs +++ b/Source/NDragDrop/DraggableVisualFeedback.xaml.cs @@ -11,13 +11,18 @@ namespace NDragDrop { - public partial class DraggableVisualFeedback + public partial class DraggableVisualFeedback : Window { private const int GwlExstyle = -20; private const int WsExTransparent = 0x00000020; private readonly ISystemMouse _systemMouse; private readonly System.Windows.Point _grabPosition; + private readonly Rect _bounds; + private readonly DrawingVisual _drawingVisual; + + private Matrix _fromScreenTransform = Matrix.Identity; + private Matrix _toScreenTransform = Matrix.Identity; public DraggableVisualFeedback() { @@ -31,22 +36,13 @@ public DraggableVisualFeedback(UIElement uiElement) : this() { _grabPosition = Mouse.GetPosition(uiElement); - - var bounds = VisualTreeHelper.GetDescendantBounds(uiElement); - var renderTargetBitmap = new RenderTargetBitmap((int)bounds.Width, (int)bounds.Height, 96, 96, PixelFormats.Pbgra32); - - var drawingVisual = new DrawingVisual(); - using (var drawingContext = drawingVisual.RenderOpen()) + _bounds = VisualTreeHelper.GetDescendantBounds(uiElement); + _drawingVisual = new DrawingVisual(); + using (var drawingContext = _drawingVisual.RenderOpen()) { var visualBrush = new VisualBrush(uiElement); - drawingContext.DrawRectangle(visualBrush, null, new Rect(new System.Windows.Point(), bounds.Size)); + drawingContext.DrawRectangle(visualBrush, null, new Rect(new System.Windows.Point(), _bounds.Size)); } - - renderTargetBitmap.Render(drawingVisual); - - MaxWidth = renderTargetBitmap.PixelWidth; - MaxHeight = renderTargetBitmap.PixelHeight; - TheImage.Source = renderTargetBitmap; } [DllImport("Kernel32")] @@ -76,20 +72,48 @@ private static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong) private void OnSourceInitialized(object sender, EventArgs eventArgs) { + InitDeviceTransforms(); + RenderBitmap(); + var hWnd = new WindowInteropHelper(this).Handle; var windowLongPtr = GetWindowLong(hWnd, GwlExstyle); if (windowLongPtr == IntPtr.Zero) return; windowLongPtr = (IntPtr.Size == 4) - ? (IntPtr) (windowLongPtr.ToInt32() | WsExTransparent) - : (IntPtr) (windowLongPtr.ToInt64() | WsExTransparent); + ? (IntPtr)(windowLongPtr.ToInt32() | WsExTransparent) + : (IntPtr)(windowLongPtr.ToInt64() | WsExTransparent); SetLastError(0); SetWindowLong(hWnd, GwlExstyle, windowLongPtr); } + private void InitDeviceTransforms() + { + PresentationSource source = PresentationSource.FromVisual(this); + if (source == null) return; + if (source.CompositionTarget == null) return; + + _fromScreenTransform = source.CompositionTarget.TransformFromDevice; + _toScreenTransform = source.CompositionTarget.TransformToDevice; + } + + private void RenderBitmap() + { + var resolution = new Vector(96.0, 96.0) * _toScreenTransform; + var pixelSize = new Vector(_bounds.Width, _bounds.Height) * _toScreenTransform; + + var renderTargetBitmap = new RenderTargetBitmap( + (int)pixelSize.X, (int)pixelSize.Y, + resolution.X, resolution.Y, PixelFormats.Pbgra32); + renderTargetBitmap.Render(_drawingVisual); + + MaxWidth = _bounds.Width; + MaxHeight = _bounds.Height; + TheImage.Source = renderTargetBitmap; + } + private void MousePositionChanged(object sender, MousePositionChangedEventArgs eventargs) { Dispatcher.BeginInvoke(new Action(UpdateLocation), eventargs.Position); @@ -97,8 +121,11 @@ private void MousePositionChanged(object sender, MousePositionChangedEventArgs e private void UpdateLocation(Point location) { - Left = location.X -_grabPosition.X; - Top = location.Y - _grabPosition.Y; + Vector locationVec = new Vector(location.X, location.Y); + Vector transformedLocation = locationVec * _fromScreenTransform; + + Left = transformedLocation.X - _grabPosition.X; + Top = transformedLocation.Y - _grabPosition.Y; } } }