using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; namespace Kniip.Capture; /// Rond vergrootglas met kruisdraad en coördinaten dat naast de muisaanwijzer meeloopt. public partial class MagnifierControl : UserControl { private const int Pixels = 15; private const double CursorOffset = 20; private static MagnifierControl? _visible; private readonly WriteableBitmap _zoom = new(Pixels, Pixels, 96, 96, PixelFormats.Bgra32, null); private readonly byte[] _buffer = new byte[Pixels * Pixels * 4]; private readonly TranslateTransform _offset = new(); public MagnifierControl() { InitializeComponent(); Zoom.Source = _zoom; RenderTransform = _offset; Visibility = Visibility.Collapsed; Unloaded += (_, _) => Hide(); } /// Vastgelegd beeld van het scherm. /// Muispositie in pixels van . /// Muispositie in fysieke bureaubladcoördinaten, voor de tekst. /// Muispositie in het venster (DIP). /// Grootte van het venster (DIP). public void Show(BitmapSource frozen, System.Drawing.Point relative, System.Drawing.Point screen, Point cursor, Size area) { // Elk scherm heeft een eigen overlay; een overlay krijgt soms muisbewegingen terwijl de aanwijzer op een ander scherm staat. if (relative.X < 0 || relative.Y < 0 || relative.X >= frozen.PixelWidth || relative.Y >= frozen.PixelHeight) { Hide(); return; } if (_visible != this) { _visible?.Hide(); _visible = this; } CopyPixels(frozen, relative); CoordinateText.Text = $"X: {screen.X} Y: {screen.Y}"; Visibility = Visibility.Visible; Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); Size size = DesiredSize; double left = cursor.X + CursorOffset; if (left + size.Width > area.Width) { left = cursor.X - CursorOffset - size.Width; } double top = cursor.Y + CursorOffset; if (top + size.Height > area.Height) { top = cursor.Y - CursorOffset - size.Height; } _offset.X = Math.Max(0, left); _offset.Y = Math.Max(0, top); } public void Hide() { Visibility = Visibility.Collapsed; if (_visible == this) { _visible = null; } } private void CopyPixels(BitmapSource frozen, System.Drawing.Point center) { Array.Clear(_buffer); for (int i = 3; i < _buffer.Length; i += 4) { _buffer[i] = 255; } int half = Pixels / 2; int x0 = Math.Max(0, center.X - half); int y0 = Math.Max(0, center.Y - half); int x1 = Math.Min(frozen.PixelWidth, center.X + half + 1); int y1 = Math.Min(frozen.PixelHeight, center.Y + half + 1); if (x1 > x0 && y1 > y0) { int offset = ((y0 - (center.Y - half)) * Pixels + (x0 - (center.X - half))) * 4; frozen.CopyPixels(new Int32Rect(x0, y0, x1 - x0, y1 - y0), _buffer, Pixels * 4, offset); } _zoom.WritePixels(new Int32Rect(0, 0, Pixels, Pixels), _buffer, Pixels * 4, 0); } }