Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 45 additions & 18 deletions Source/NDragDrop/DraggableVisualFeedback.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand All @@ -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")]
Expand Down Expand Up @@ -76,29 +72,60 @@ 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<Point>(UpdateLocation), eventargs.Position);
}

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;
}
}
}