From 14415cd05ef879fc8c0570d54a08aa8b8c8344ac Mon Sep 17 00:00:00 2001 From: FastDeath Date: Mon, 25 Jun 2018 21:47:54 +0200 Subject: [PATCH 1/2] Add dpi-aware mouse location transformation --- .../NDragDrop/DraggableVisualFeedback.xaml.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Source/NDragDrop/DraggableVisualFeedback.xaml.cs b/Source/NDragDrop/DraggableVisualFeedback.xaml.cs index b6614a6..87b699a 100644 --- a/Source/NDragDrop/DraggableVisualFeedback.xaml.cs +++ b/Source/NDragDrop/DraggableVisualFeedback.xaml.cs @@ -11,13 +11,14 @@ 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 Matrix _mousePosTransform = Matrix.Identity; public DraggableVisualFeedback() { @@ -34,7 +35,7 @@ public DraggableVisualFeedback(UIElement 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()) { @@ -76,14 +77,17 @@ private static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong) private void OnSourceInitialized(object sender, EventArgs eventArgs) { + PresentationSource source = PresentationSource.FromVisual(this); + _mousePosTransform = source?.CompositionTarget?.TransformFromDevice ?? Matrix.Identity; + 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); @@ -97,8 +101,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 = Vector.Multiply(locationVec, _mousePosTransform); + + Left = transformedLocation.X - _grabPosition.X; + Top = transformedLocation.Y - _grabPosition.Y; } } } From 833f5ae350573a9f5c290a394e58b2e226bd2cb6 Mon Sep 17 00:00:00 2001 From: FastDeath Date: Mon, 25 Jun 2018 22:32:21 +0200 Subject: [PATCH 2/2] Add dpi-aware rendered bitmap resolution --- .../NDragDrop/DraggableVisualFeedback.xaml.cs | 54 +++++++++++++------ 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/Source/NDragDrop/DraggableVisualFeedback.xaml.cs b/Source/NDragDrop/DraggableVisualFeedback.xaml.cs index 87b699a..42f2d4a 100644 --- a/Source/NDragDrop/DraggableVisualFeedback.xaml.cs +++ b/Source/NDragDrop/DraggableVisualFeedback.xaml.cs @@ -18,7 +18,11 @@ public partial class DraggableVisualFeedback : Window private readonly ISystemMouse _systemMouse; private readonly System.Windows.Point _grabPosition; - private Matrix _mousePosTransform = Matrix.Identity; + private readonly Rect _bounds; + private readonly DrawingVisual _drawingVisual; + + private Matrix _fromScreenTransform = Matrix.Identity; + private Matrix _toScreenTransform = Matrix.Identity; public DraggableVisualFeedback() { @@ -32,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")] @@ -77,8 +72,8 @@ private static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong) private void OnSourceInitialized(object sender, EventArgs eventArgs) { - PresentationSource source = PresentationSource.FromVisual(this); - _mousePosTransform = source?.CompositionTarget?.TransformFromDevice ?? Matrix.Identity; + InitDeviceTransforms(); + RenderBitmap(); var hWnd = new WindowInteropHelper(this).Handle; @@ -94,6 +89,31 @@ private void OnSourceInitialized(object sender, EventArgs eventArgs) 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); @@ -102,7 +122,7 @@ private void MousePositionChanged(object sender, MousePositionChangedEventArgs e private void UpdateLocation(Point location) { Vector locationVec = new Vector(location.X, location.Y); - Vector transformedLocation = Vector.Multiply(locationVec, _mousePosTransform); + Vector transformedLocation = locationVec * _fromScreenTransform; Left = transformedLocation.X - _grabPosition.X; Top = transformedLocation.Y - _grabPosition.Y;