724 lines
26 KiB
C#
724 lines
26 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using HandyControl.Data;
|
|
using HandyControl.Tools;
|
|
using HandyControl.Tools.Extension;
|
|
using HandyControl.Tools.Interop;
|
|
|
|
namespace HandyControl.Controls
|
|
{
|
|
[TemplatePart(Name = ElementCanvas, Type = typeof(InkCanvas))]
|
|
[TemplatePart(Name = ElementMaskAreaLeft, Type = typeof(FrameworkElement))]
|
|
[TemplatePart(Name = ElementMaskAreaTop, Type = typeof(FrameworkElement))]
|
|
[TemplatePart(Name = ElementMaskAreaRight, Type = typeof(FrameworkElement))]
|
|
[TemplatePart(Name = ElementMaskAreaBottom, Type = typeof(FrameworkElement))]
|
|
[TemplatePart(Name = ElementTargetArea, Type = typeof(InkCanvas))]
|
|
[TemplatePart(Name = ElementMagnifier, Type = typeof(FrameworkElement))]
|
|
public class ScreenshotWindow : System.Windows.Window
|
|
{
|
|
#region fields
|
|
|
|
private readonly Screenshot _screenshot;
|
|
|
|
private VisualBrush _visualPreview;
|
|
|
|
private Size _viewboxSize;
|
|
|
|
private BitmapSource _imageSource;
|
|
|
|
private static readonly Guid BmpGuid = new Guid("{b96b3cab-0728-11d3-9d7b-0000f81ef32e}");
|
|
|
|
#region const
|
|
|
|
private const int IntervalLength = 1;
|
|
|
|
private const int IntervalBigLength = 10;
|
|
|
|
private const int SnapLength = 4;
|
|
|
|
#endregion
|
|
|
|
#region IntPtr
|
|
|
|
private IntPtr _desktopWindowHandle;
|
|
|
|
private IntPtr _mouseOverWindowHandle;
|
|
|
|
private readonly IntPtr _screenshotWindowHandle;
|
|
|
|
#endregion
|
|
|
|
#region status
|
|
|
|
private InteropValues.RECT _desktopWindowRect;
|
|
|
|
private InteropValues.RECT _targetWindowRect;
|
|
|
|
private readonly int[] _flagArr = new int[4];
|
|
|
|
private bool _isOut;
|
|
|
|
private bool _canDrag;
|
|
|
|
private bool _receiveMoveMsg = true;
|
|
|
|
private Point _mousePointOld;
|
|
|
|
private Point _pointFixed;
|
|
|
|
private InteropValues.POINT _pointFloating;
|
|
|
|
private bool _saveScreenshot;
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Elements
|
|
|
|
internal InkCanvas Canvas { get; set; }
|
|
|
|
internal FrameworkElement MaskAreaLeft { get; set; }
|
|
|
|
internal FrameworkElement MaskAreaTop { get; set; }
|
|
|
|
internal FrameworkElement MaskAreaRight { get; set; }
|
|
|
|
internal FrameworkElement MaskAreaBottom { get; set; }
|
|
|
|
internal FrameworkElement TargetArea { get; set; }
|
|
|
|
private FrameworkElement _magnifier;
|
|
|
|
#endregion
|
|
|
|
#region const
|
|
|
|
private const string ElementCanvas = "PART_Canvas";
|
|
|
|
private const string ElementMaskAreaLeft = "PART_MaskAreaLeft";
|
|
|
|
private const string ElementMaskAreaTop = "PART_MaskAreaTop";
|
|
|
|
private const string ElementMaskAreaRight = "PART_MaskAreaRight";
|
|
|
|
private const string ElementMaskAreaBottom = "PART_MaskAreaBottom";
|
|
|
|
private const string ElementTargetArea = "PART_TargetArea";
|
|
|
|
private const string ElementMagnifier = "PART_Magnifier";
|
|
|
|
#endregion
|
|
|
|
#region prop
|
|
|
|
public static readonly DependencyProperty IsDrawingProperty = DependencyProperty.Register(
|
|
"IsDrawing", typeof(bool), typeof(ScreenshotWindow), new PropertyMetadata(ValueBoxes.FalseBox));
|
|
|
|
public bool IsDrawing
|
|
{
|
|
get => (bool) GetValue(IsDrawingProperty);
|
|
internal set => SetValue(IsDrawingProperty, ValueBoxes.BooleanBox(value));
|
|
}
|
|
|
|
public static readonly DependencyProperty IsSelectingProperty = DependencyProperty.Register(
|
|
"IsSelecting", typeof(bool), typeof(ScreenshotWindow), new PropertyMetadata(ValueBoxes.FalseBox));
|
|
|
|
public bool IsSelecting
|
|
{
|
|
get => (bool) GetValue(IsSelectingProperty);
|
|
internal set => SetValue(IsSelectingProperty, ValueBoxes.BooleanBox(value));
|
|
}
|
|
|
|
public static readonly DependencyProperty SizeProperty = DependencyProperty.Register(
|
|
"Size", typeof(Size), typeof(ScreenshotWindow), new PropertyMetadata(default(Size)));
|
|
|
|
public Size Size
|
|
{
|
|
get => (Size) GetValue(SizeProperty);
|
|
internal set => SetValue(SizeProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty SizeStrProperty = DependencyProperty.Register(
|
|
"SizeStr", typeof(string), typeof(ScreenshotWindow), new PropertyMetadata(default(string)));
|
|
|
|
public string SizeStr
|
|
{
|
|
get => (string) GetValue(SizeStrProperty);
|
|
internal set => SetValue(SizeStrProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty PixelColorProperty = DependencyProperty.Register(
|
|
"PixelColor", typeof(Color), typeof(ScreenshotWindow), new PropertyMetadata(default(Color)));
|
|
|
|
public Color PixelColor
|
|
{
|
|
get => (Color) GetValue(PixelColorProperty);
|
|
internal set => SetValue(PixelColorProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyProperty PixelColorStrProperty = DependencyProperty.Register(
|
|
"PixelColorStr", typeof(string), typeof(ScreenshotWindow), new PropertyMetadata(default(string)));
|
|
|
|
public string PixelColorStr
|
|
{
|
|
get => (string) GetValue(PixelColorStrProperty);
|
|
internal set => SetValue(PixelColorStrProperty, value);
|
|
}
|
|
|
|
public static readonly DependencyPropertyKey PreviewBrushPropertyKey = DependencyProperty.RegisterReadOnly(
|
|
"PreviewBrush", typeof(Brush), typeof(ScreenshotWindow), new PropertyMetadata(default(Brush)));
|
|
|
|
public static readonly DependencyProperty PreviewBrushProperty = PreviewBrushPropertyKey.DependencyProperty;
|
|
|
|
public Brush PreviewBrush
|
|
{
|
|
get => (Brush) GetValue(PreviewBrushProperty);
|
|
set => SetValue(PreviewBrushProperty, value);
|
|
}
|
|
|
|
#endregion
|
|
|
|
public ScreenshotWindow(Screenshot screenshot)
|
|
{
|
|
Style = ResourceHelper.GetResource<Style>(ResourceToken.Window4ScreenshotStyle);
|
|
_screenshot = screenshot;
|
|
DataContext = this;
|
|
|
|
_screenshotWindowHandle = this.GetHandle();
|
|
InteropMethods.EnableWindow(_screenshotWindowHandle, false);
|
|
|
|
Loaded += ScreenshotWindow_Loaded;
|
|
Closed += ScreenshotWindow_Closed;
|
|
}
|
|
|
|
public override void OnApplyTemplate()
|
|
{
|
|
base.OnApplyTemplate();
|
|
|
|
Canvas = GetTemplateChild(ElementCanvas) as InkCanvas;
|
|
MaskAreaLeft = GetTemplateChild(ElementMaskAreaLeft) as FrameworkElement;
|
|
MaskAreaTop = GetTemplateChild(ElementMaskAreaTop) as FrameworkElement;
|
|
MaskAreaRight = GetTemplateChild(ElementMaskAreaRight) as FrameworkElement;
|
|
MaskAreaBottom = GetTemplateChild(ElementMaskAreaBottom) as FrameworkElement;
|
|
TargetArea = GetTemplateChild(ElementTargetArea) as FrameworkElement;
|
|
_magnifier = GetTemplateChild(ElementMagnifier) as FrameworkElement;
|
|
|
|
if (_magnifier != null)
|
|
{
|
|
_viewboxSize = new Size(29, 21);
|
|
}
|
|
|
|
_visualPreview = new VisualBrush(Canvas)
|
|
{
|
|
ViewboxUnits = BrushMappingMode.Absolute
|
|
};
|
|
SetValue(PreviewBrushPropertyKey, _visualPreview);
|
|
_magnifier.Show();
|
|
}
|
|
|
|
protected override void OnPreviewKeyDown(KeyEventArgs e)
|
|
{
|
|
if (e.Key == Key.Escape) Close();
|
|
|
|
if (IsDrawing)
|
|
{
|
|
switch (e.Key)
|
|
{
|
|
case Key.Left:
|
|
{
|
|
MoveTargetArea(MoveRect(_targetWindowRect, -1, rightFlag: -1));
|
|
}
|
|
break;
|
|
case Key.Up:
|
|
{
|
|
MoveTargetArea(MoveRect(_targetWindowRect, bottomFlag: -1, topFlag: -1));
|
|
}
|
|
break;
|
|
case Key.Right:
|
|
{
|
|
MoveTargetArea(MoveRect(_targetWindowRect, 1, rightFlag: 1));
|
|
}
|
|
break;
|
|
case Key.Down:
|
|
{
|
|
MoveTargetArea(MoveRect(_targetWindowRect, bottomFlag: 1, topFlag: 1));
|
|
}
|
|
break;
|
|
case Key.Enter:
|
|
_saveScreenshot = true;
|
|
Close();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) => _mousePointOld = e.GetPosition(this);
|
|
|
|
protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e) => _magnifier.Collapse();
|
|
|
|
protected override void OnPreviewMouseDoubleClick(MouseButtonEventArgs e)
|
|
{
|
|
_saveScreenshot = true;
|
|
Close();
|
|
}
|
|
|
|
protected override void OnPreviewMouseMove(MouseEventArgs e)
|
|
{
|
|
if (e.LeftButton != MouseButtonState.Pressed)
|
|
{
|
|
UpdateStatus(e.GetPosition(TargetArea));
|
|
return;
|
|
}
|
|
|
|
var newPoint = Mouse.GetPosition(this);
|
|
var offsetX = (int) (newPoint.X - _mousePointOld.X);
|
|
var offsetY = (int) (newPoint.Y - _mousePointOld.Y);
|
|
|
|
if (IsDrawing)
|
|
{
|
|
if (_isOut) return;
|
|
var rect = _targetWindowRect;
|
|
|
|
if (_canDrag)
|
|
{
|
|
rect.Left += offsetX;
|
|
rect.Top += offsetY;
|
|
rect.Right += offsetX;
|
|
rect.Bottom += offsetY;
|
|
}
|
|
else
|
|
{
|
|
var magnifierPos = new InteropValues.POINT((int) newPoint.X, (int) newPoint.Y);
|
|
|
|
if (_flagArr[0] > 0)
|
|
{
|
|
_pointFloating.X += offsetX * _flagArr[0];
|
|
magnifierPos.X = _pointFloating.X;
|
|
}
|
|
else if (_flagArr[2] > 0)
|
|
{
|
|
_pointFloating.X += offsetX * _flagArr[2];
|
|
magnifierPos.X = _pointFloating.X - 1;
|
|
}
|
|
|
|
if (_flagArr[1] > 0)
|
|
{
|
|
_pointFloating.Y += offsetY * _flagArr[1];
|
|
magnifierPos.Y = _pointFloating.Y;
|
|
}
|
|
else if (_flagArr[3] > 0)
|
|
{
|
|
_pointFloating.Y += offsetY * _flagArr[3];
|
|
magnifierPos.Y = _pointFloating.Y - 1;
|
|
}
|
|
|
|
rect.Left = (int) Math.Min(_pointFixed.X, _pointFloating.X);
|
|
rect.Top = (int) Math.Min(_pointFixed.Y, _pointFloating.Y);
|
|
rect.Right = (int) Math.Max(_pointFixed.X, _pointFloating.X);
|
|
rect.Bottom = (int) Math.Max(_pointFixed.Y, _pointFloating.Y);
|
|
|
|
_magnifier.Show();
|
|
MoveMagnifier(magnifierPos);
|
|
}
|
|
|
|
MoveTargetArea(rect);
|
|
_mousePointOld = newPoint;
|
|
}
|
|
else if (IsSelecting)
|
|
{
|
|
var minX = (int) Math.Min(_mousePointOld.X, newPoint.X);
|
|
var maxX = (int) Math.Max(_mousePointOld.X, newPoint.X);
|
|
var minY = (int) Math.Min(_mousePointOld.Y, newPoint.Y);
|
|
var maxY = (int) Math.Max(_mousePointOld.Y, newPoint.Y);
|
|
|
|
MoveTargetArea(new InteropValues.RECT(minX, minY, maxX, maxY));
|
|
}
|
|
else if (!IsSelecting && offsetX > 0 && offsetY > 0)
|
|
{
|
|
IsSelecting = true;
|
|
}
|
|
}
|
|
|
|
private void ScreenshotWindow_Closed(object sender, EventArgs e)
|
|
{
|
|
if (_saveScreenshot)
|
|
{
|
|
SaveScreenshot();
|
|
}
|
|
|
|
StopHooks();
|
|
IsDrawing = false;
|
|
|
|
Loaded -= ScreenshotWindow_Loaded;
|
|
Closed -= ScreenshotWindow_Closed;
|
|
}
|
|
|
|
private void ScreenshotWindow_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
_imageSource = GetDesktopSnapshot();
|
|
var image = new Image
|
|
{
|
|
Source = _imageSource
|
|
};
|
|
RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.NearestNeighbor);
|
|
Canvas.Children.Add(image);
|
|
StartHooks();
|
|
InteropMethods.GetCursorPos(out var point);
|
|
MoveElement(point);
|
|
MoveMagnifier(point);
|
|
}
|
|
|
|
private void UpdateStatus(Point point)
|
|
{
|
|
Cursor cursor;
|
|
|
|
var leftAbs = Math.Abs(point.X);
|
|
var topAbs = Math.Abs(point.Y);
|
|
var rightAbs = Math.Abs(point.X - _targetWindowRect.Width);
|
|
var downAbs = Math.Abs(point.Y - _targetWindowRect.Height);
|
|
|
|
_canDrag = false;
|
|
_isOut = false;
|
|
_flagArr[0] = 0;
|
|
_flagArr[1] = 0;
|
|
_flagArr[2] = 0;
|
|
_flagArr[3] = 0;
|
|
|
|
if (leftAbs <= SnapLength)
|
|
{
|
|
if (topAbs > SnapLength)
|
|
{
|
|
if (downAbs > SnapLength)
|
|
{
|
|
// left
|
|
cursor = Cursors.SizeWE;
|
|
_pointFixed = new Point(_targetWindowRect.Right, _targetWindowRect.Top);
|
|
_pointFloating = new InteropValues.POINT(_targetWindowRect.Left, _targetWindowRect.Bottom);
|
|
_flagArr[0] = 1;
|
|
}
|
|
else
|
|
{
|
|
//left bottom
|
|
cursor = Cursors.SizeNESW;
|
|
_pointFixed = new Point(_targetWindowRect.Right, _targetWindowRect.Top);
|
|
_pointFloating = new InteropValues.POINT(_targetWindowRect.Left, _targetWindowRect.Bottom);
|
|
_flagArr[0] = 1;
|
|
_flagArr[3] = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// left top
|
|
cursor = Cursors.SizeNWSE;
|
|
_pointFixed = new Point(_targetWindowRect.Right, _targetWindowRect.Bottom);
|
|
_pointFloating = new InteropValues.POINT(_targetWindowRect.Left, _targetWindowRect.Top);
|
|
_flagArr[0] = 1;
|
|
_flagArr[1] = 1;
|
|
}
|
|
}
|
|
else if (rightAbs > SnapLength)
|
|
{
|
|
if (topAbs > SnapLength)
|
|
{
|
|
if (downAbs > SnapLength)
|
|
{
|
|
if (TargetArea.IsMouseOver)
|
|
{
|
|
//drag
|
|
cursor = Cursors.SizeAll;
|
|
_canDrag = true;
|
|
}
|
|
else
|
|
{
|
|
//out
|
|
cursor = Cursors.Arrow;
|
|
_isOut = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//bottom
|
|
cursor = Cursors.SizeNS;
|
|
_pointFixed = new Point(_targetWindowRect.Left, _targetWindowRect.Top);
|
|
_pointFloating = new InteropValues.POINT(_targetWindowRect.Right, _targetWindowRect.Bottom);
|
|
_flagArr[3] = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//top
|
|
cursor = Cursors.SizeNS;
|
|
_pointFixed = new Point(_targetWindowRect.Right, _targetWindowRect.Bottom);
|
|
_pointFloating = new InteropValues.POINT(_targetWindowRect.Left, _targetWindowRect.Top);
|
|
_flagArr[1] = 1;
|
|
}
|
|
}
|
|
else if (rightAbs <= SnapLength)
|
|
{
|
|
if (topAbs > SnapLength)
|
|
{
|
|
if (downAbs > SnapLength)
|
|
{
|
|
//right
|
|
cursor = Cursors.SizeWE;
|
|
_pointFixed = new Point(_targetWindowRect.Left, _targetWindowRect.Bottom);
|
|
_pointFloating = new InteropValues.POINT(_targetWindowRect.Right, _targetWindowRect.Top);
|
|
_flagArr[2] = 1;
|
|
}
|
|
else
|
|
{
|
|
//right bottom
|
|
cursor = Cursors.SizeNWSE;
|
|
_pointFixed = new Point(_targetWindowRect.Left, _targetWindowRect.Top);
|
|
_pointFloating = new InteropValues.POINT(_targetWindowRect.Right, _targetWindowRect.Bottom);
|
|
_flagArr[2] = 1;
|
|
_flagArr[3] = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// right top
|
|
cursor = Cursors.SizeNESW;
|
|
_pointFixed = new Point(_targetWindowRect.Left, _targetWindowRect.Bottom);
|
|
_pointFloating = new InteropValues.POINT(_targetWindowRect.Right, _targetWindowRect.Top);
|
|
_flagArr[1] = 1;
|
|
_flagArr[2] = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//out
|
|
cursor = Cursors.Arrow;
|
|
_isOut = true;
|
|
}
|
|
|
|
TargetArea.Cursor = cursor;
|
|
}
|
|
|
|
private void StopHooks()
|
|
{
|
|
MouseHook.Stop();
|
|
MouseHook.StatusChanged -= MouseHook_StatusChanged;
|
|
}
|
|
|
|
private void StartHooks()
|
|
{
|
|
MouseHook.Start();
|
|
MouseHook.StatusChanged += MouseHook_StatusChanged;
|
|
}
|
|
|
|
private void MouseHook_StatusChanged(object sender, MouseHookEventArgs e)
|
|
{
|
|
switch (e.MessageType)
|
|
{
|
|
case MouseHookMessageType.MouseMove:
|
|
MoveElement(e.Point);
|
|
MoveMagnifier(e.Point);
|
|
break;
|
|
case MouseHookMessageType.LeftButtonDown:
|
|
_receiveMoveMsg = false;
|
|
_mousePointOld = new Point(e.Point.X, e.Point.Y);
|
|
InteropMethods.EnableWindow(_screenshotWindowHandle, true);
|
|
break;
|
|
case MouseHookMessageType.RightButtonDown:
|
|
if (!IsDrawing) Close();
|
|
break;
|
|
case MouseHookMessageType.LeftButtonUp:
|
|
StopHooks();
|
|
IsSelecting = false;
|
|
IsDrawing = true;
|
|
_magnifier.Collapse();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void SaveScreenshot()
|
|
{
|
|
var cb = new CroppedBitmap(_imageSource, new Int32Rect(_targetWindowRect.Left, _targetWindowRect.Top, _targetWindowRect.Width, _targetWindowRect.Height));
|
|
_screenshot.OnSnapped(cb);
|
|
|
|
Close();
|
|
}
|
|
|
|
private BitmapSource GetDesktopSnapshot()
|
|
{
|
|
_desktopWindowHandle = InteropMethods.GetDesktopWindow();
|
|
var hdcSrc = InteropMethods.GetWindowDC(_desktopWindowHandle);
|
|
var hdcDest = InteropMethods.CreateCompatibleDC(hdcSrc);
|
|
|
|
InteropMethods.GetWindowRect(_desktopWindowHandle, out _desktopWindowRect);
|
|
var desktopWindowWidth = _desktopWindowRect.Right - _desktopWindowRect.Left;
|
|
var desktopWindowHeight = _desktopWindowRect.Bottom - _desktopWindowRect.Top;
|
|
|
|
var hbitmap = InteropMethods.CreateCompatibleBitmap(hdcSrc, desktopWindowWidth, desktopWindowHeight);
|
|
var hOld = InteropMethods.SelectObject(hdcDest, hbitmap);
|
|
InteropMethods.BitBlt(hdcDest, 0, 0, desktopWindowWidth, desktopWindowHeight, hdcSrc, 0, 0, InteropValues.SRCCOPY);
|
|
InteropMethods.SelectObject(hdcDest, hOld);
|
|
InteropMethods.DeleteDC(hdcDest);
|
|
InteropMethods.ReleaseDC(_desktopWindowHandle, hdcSrc);
|
|
|
|
var status = InteropMethods.Gdip.GdipCreateBitmapFromHBITMAP(new HandleRef(null, hbitmap), new HandleRef(null, IntPtr.Zero), out var bitmap);
|
|
if (status != InteropMethods.Gdip.Ok) throw InteropMethods.Gdip.StatusException(status);
|
|
|
|
using var ms = new MemoryStream();
|
|
status = InteropMethods.Gdip.GdipGetImageEncodersSize(out var numEncoders, out var size);
|
|
if (status != InteropMethods.Gdip.Ok) throw InteropMethods.Gdip.StatusException(status);
|
|
|
|
var memory = Marshal.AllocHGlobal(size);
|
|
try
|
|
{
|
|
status = InteropMethods.Gdip.GdipGetImageEncoders(numEncoders, size, memory);
|
|
if (status != InteropMethods.Gdip.Ok) throw InteropMethods.Gdip.StatusException(status);
|
|
|
|
var codecInfo = ImageCodecInfo.ConvertFromMemory(memory, numEncoders).FirstOrDefault(item => item.FormatID.Equals(BmpGuid));
|
|
if (codecInfo == null) throw new Exception("ImageCodecInfo is null");
|
|
|
|
var encoderParamsMemory = IntPtr.Zero;
|
|
|
|
try
|
|
{
|
|
var g = codecInfo.Clsid;
|
|
status = InteropMethods.Gdip.GdipSaveImageToStream(new HandleRef(this, bitmap),
|
|
new InteropValues.ComStreamFromDataStream(ms), ref g,
|
|
new HandleRef(null, encoderParamsMemory));
|
|
}
|
|
finally
|
|
{
|
|
if (encoderParamsMemory != IntPtr.Zero)
|
|
{
|
|
Marshal.FreeHGlobal(encoderParamsMemory);
|
|
}
|
|
}
|
|
|
|
if (status != InteropMethods.Gdip.Ok)
|
|
{
|
|
throw InteropMethods.Gdip.StatusException(status);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(memory);
|
|
}
|
|
|
|
var bitmapImage = new BitmapImage();
|
|
bitmapImage.BeginInit();
|
|
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
|
bitmapImage.StreamSource = ms;
|
|
bitmapImage.EndInit();
|
|
bitmapImage.Freeze();
|
|
return bitmapImage;
|
|
}
|
|
|
|
private void MoveElement(InteropValues.POINT point)
|
|
{
|
|
if (!_receiveMoveMsg) return;
|
|
|
|
var mouseOverWindowHandle = InteropMethods.ChildWindowFromPointEx(_desktopWindowHandle,
|
|
new InteropValues.POINT
|
|
{
|
|
X = point.X,
|
|
Y = point.Y
|
|
}, 1 | 2);
|
|
|
|
if (mouseOverWindowHandle != _mouseOverWindowHandle && mouseOverWindowHandle != IntPtr.Zero)
|
|
{
|
|
_mouseOverWindowHandle = mouseOverWindowHandle;
|
|
|
|
InteropMethods.GetWindowRect(_mouseOverWindowHandle, out var windowRect);
|
|
MoveTargetArea(windowRect);
|
|
}
|
|
}
|
|
|
|
private static InteropValues.RECT MoveRect(InteropValues.RECT rect, int leftFlag = 0, int topFlag = 0, int rightFlag = 0, int bottomFlag = 0)
|
|
{
|
|
var moveLength = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)
|
|
? IntervalBigLength
|
|
: IntervalLength;
|
|
|
|
rect.Left += leftFlag * moveLength;
|
|
rect.Top += topFlag * moveLength;
|
|
rect.Right += rightFlag * moveLength;
|
|
rect.Bottom += bottomFlag * moveLength;
|
|
|
|
return rect;
|
|
}
|
|
|
|
private void MoveTargetArea(InteropValues.RECT rect)
|
|
{
|
|
if (rect.Left < 0)
|
|
{
|
|
rect.Right -= rect.Left;
|
|
rect.Left = 0;
|
|
}
|
|
|
|
if (rect.Top < 0)
|
|
{
|
|
rect.Bottom -= rect.Top;
|
|
rect.Top = 0;
|
|
}
|
|
|
|
if (rect.Right > _desktopWindowRect.Width)
|
|
{
|
|
rect.Left -= rect.Right - _desktopWindowRect.Width;
|
|
rect.Right = _desktopWindowRect.Width;
|
|
}
|
|
|
|
if (rect.Bottom > _desktopWindowRect.Height)
|
|
{
|
|
rect.Top -= rect.Bottom - _desktopWindowRect.Height;
|
|
rect.Bottom = _desktopWindowRect.Height;
|
|
}
|
|
|
|
rect.Left = Math.Max(0, rect.Left);
|
|
rect.Top = Math.Max(0, rect.Top);
|
|
|
|
var width = rect.Width;
|
|
var height = rect.Height;
|
|
var left = rect.Left;
|
|
var top = rect.Top;
|
|
|
|
TargetArea.Width = width;
|
|
TargetArea.Height = height;
|
|
TargetArea.Margin = new Thickness(left, top, 0, 0);
|
|
|
|
_targetWindowRect = new InteropValues.RECT(left, top, left + width, top + height);
|
|
Size = _targetWindowRect.Size;
|
|
SizeStr = $"{_targetWindowRect.Width} x {_targetWindowRect.Height}";
|
|
|
|
MoveMaskArea();
|
|
}
|
|
|
|
private void MoveMaskArea()
|
|
{
|
|
MaskAreaLeft.Width = TargetArea.Margin.Left;
|
|
MaskAreaLeft.Height = _desktopWindowRect.Height;
|
|
|
|
MaskAreaTop.Margin = new Thickness(TargetArea.Margin.Left, 0, 0, 0);
|
|
MaskAreaTop.Width = TargetArea.Width;
|
|
MaskAreaTop.Height = TargetArea.Margin.Top;
|
|
|
|
MaskAreaRight.Margin = new Thickness(TargetArea.Width + TargetArea.Margin.Left, 0, 0, 0);
|
|
MaskAreaRight.Width = _desktopWindowRect.Width - TargetArea.Margin.Left - TargetArea.Width;
|
|
MaskAreaRight.Height = _desktopWindowRect.Height;
|
|
|
|
MaskAreaBottom.Margin = new Thickness(TargetArea.Margin.Left, TargetArea.Height + TargetArea.Margin.Top, 0, 0);
|
|
MaskAreaBottom.Width = TargetArea.Width;
|
|
MaskAreaBottom.Height = _desktopWindowRect.Height - TargetArea.Height - TargetArea.Margin.Top;
|
|
}
|
|
|
|
private void MoveMagnifier(InteropValues.POINT point)
|
|
{
|
|
_magnifier.Margin = new Thickness(point.X + 4, point.Y + 26, 0, 0);
|
|
_visualPreview.Viewbox = new Rect(new Point(point.X - _viewboxSize.Width / 2 + 0.5, point.Y - _viewboxSize.Height / 2 + 0.5), _viewboxSize);
|
|
}
|
|
}
|
|
}
|