using System.Windows; namespace DeskCore; /// Bildschirm-Hilfen, damit Fenster nie außerhalb des sichtbaren Bereichs landen (z. B. nach Abstecken eines Monitors). public static class Screens { /// Umrechnung Pixel → WPF-Einheiten (System-DPI). public static double Scale { get { using var g = System.Drawing.Graphics.FromHwnd(IntPtr.Zero); return g.DpiX / 96.0; } } /// Arbeitsbereiche (ohne Taskleiste) aller angeschlossenen Bildschirme in WPF-Einheiten. public static List WorkAreas() { var s = Scale; return System.Windows.Forms.Screen.AllScreens .Select(m => new Rect(m.WorkingArea.X / s, m.WorkingArea.Y / s, m.WorkingArea.Width / s, m.WorkingArea.Height / s)) .ToList(); } public static Rect PrimaryWorkArea => SystemParameters.WorkArea; /// Arbeitsbereich des Bildschirms, auf dem der Punkt liegt (sonst der nächstgelegene). public static Rect WorkAreaAt(Point p) { var areas = WorkAreas(); return areas.FirstOrDefault(a => a.Contains(p), areas.OrderBy(a => Math.Pow(Math.Clamp(p.X, a.Left, a.Right) - p.X, 2) + Math.Pow(Math.Clamp(p.Y, a.Top, a.Bottom) - p.Y, 2)) .FirstOrDefault(PrimaryWorkArea)); } /// Ist genug vom Fenster (Titelleiste) auf irgendeinem Bildschirm sichtbar, um es greifen zu können? public static bool IsReachable(Rect window) { var title = new Rect(window.X, window.Y, window.Width, Math.Min(40, window.Height)); return WorkAreas().Any(a => { var i = Rect.Intersect(a, title); return !i.IsEmpty && i.Width >= Math.Min(120, window.Width / 2) && i.Height >= 20; }); } }