using AutoAgent.Domain.Exceptions; using System.Drawing; using System.Drawing.Imaging; using System.Text; namespace AutoAgent.Domain { public static class DesktopHandler { private static Rectangle GetCaptureArea(IntPtr hwnd, Models.Point pt, Models.AreaSize size) { Rectangle area; if (hwnd == IntPtr.Zero) { area = Rectangle.FromLTRB(User32Dll.GetSystemMetrics(76), User32Dll.GetSystemMetrics(77), User32Dll.GetSystemMetrics(78), User32Dll.GetSystemMetrics(79)); } else { if (User32Dll.GetClientRect(hwnd, out var rect)) { User32Dll.RECT br = new () { X = rect.Right, Y = rect.Bottom }; if (User32Dll.ClientToScreen(hwnd, ref rect) && User32Dll.ClientToScreen(hwnd, ref br)) { area = new Rectangle(rect.X, rect.Y, br.X - rect.X, br.Y - rect.Y); } else { throw new CaptureAreaException($"Could not convert client coordinates to screen coordinates for HWND: {hwnd}"); } } else { throw new CaptureAreaException($"Failed to get client rectangle for HWND: {hwnd}"); } } if (size.Width > 0 && size.Height > 0) { area = new Rectangle( Math.Max(area.X, area.X + pt.X), Math.Max(area.Y, area.Y + pt.Y), Math.Min(size.Width, area.Right - pt.X), Math.Min(size.Height, area.Bottom - pt.Y)); } if (area.Width <= 0 || area.Height <= 0) { throw new CaptureAreaException($"Final capture rectangle has invalid dimensions: {area}"); } return area; } private static bool GetWindowInfo(ref Models.WindowInfo data, IntPtr hwnd) { int length = User32Dll.GetWindowTextLength(hwnd); if (length > 0) { var sb = new StringBuilder(length + 1); User32Dll.GetWindowText(hwnd, sb, sb.Capacity); data.Title = sb.ToString(); if (User32Dll.GetCursorPos(out var pt) && User32Dll.ScreenToClient(hwnd, ref pt)) { data.CursorPosition = new Models.Point { X = pt.X, Y = pt.Y }; } if (User32Dll.GetWindowRect(hwnd, out var wRect)) { var rect = Rectangle.FromLTRB(wRect.Left, wRect.Top, wRect.Right, wRect.Bottom); data.WindowPosition = new Models.Point { X = rect.X, Y = rect.Y }; data.WindowSize = new Models.AreaSize { Width = rect.Width, Height = rect.Height }; } if (User32Dll.GetClientRect(hwnd, out var cRect)) { var rect = Rectangle.FromLTRB(cRect.Left, cRect.Top, cRect.Right, cRect.Bottom); data.ContentSize = new Models.AreaSize { Width = rect.Width, Height = rect.Height }; } return true; } return false; } private static bool TryGetWindowInfo(IntPtr hwnd, ref IntPtr foreground, out Models.WindowInfo info) { info = new(); if (User32Dll.IsWindowVisible(hwnd)) { info.Hwnd = hwnd.ToInt32(); if ((info.ThreadId = (int)User32Dll.GetWindowThreadProcessId(hwnd, out uint pid)) != 0) { info.Pid = (int)pid; if (GetWindowInfo(ref info, hwnd)) { info.IsActive = foreground.ToInt32() == info.Hwnd; return true; } } } return false; } public static Task> GetWindows(ushort max = 0, IEnumerable? whitelist = null) { if (max == 0) max = UInt16.MaxValue; if (whitelist == null) whitelist = Array.Empty(); return Task.Run(() => { var foreground = User32Dll.GetForegroundWindow(); List container = new(); User32Dll.EnumWindows(delegate (IntPtr hwnd, IntPtr lParam) { bool found = true; if (container.Count >= max) return false; foreach (var w in whitelist) { if (w == hwnd.ToInt32()) { found = true; break; } found = false; } if (found && TryGetWindowInfo(hwnd, ref foreground, out var info)) { container.Add(info); } return true; }, IntPtr.Zero); return (IEnumerable)container; }); } public static Task<(Models.AreaSize size, byte[] pngImage)> GetScreenshot(Models.Point pos, Models.AreaSize size, IntPtr hwnd = 0) { return Task.Run(() => { Rectangle area = GetCaptureArea(hwnd, pos, size); using (Bitmap screenshot = new Bitmap(area.Width, area.Height, PixelFormat.Format32bppArgb)) { using (Graphics g = Graphics.FromImage(screenshot)) { g.CopyFromScreen(area.X, area.Y, 0, 0, area.Size, CopyPixelOperation.SourceCopy); } using (MemoryStream ms = new MemoryStream()) { screenshot.Save(ms, ImageFormat.Png); return (new Models.AreaSize { Width = screenshot.Width, Height = screenshot.Height }, ms.ToArray()); } } }); } public static Task<(byte r, byte g, byte b)> GetPixelColor(Models.Point pos, IntPtr hwnd = 0) { return Task.Run(() => { Rectangle area = GetCaptureArea(hwnd, pos, new Models.AreaSize { Width = 1, Height = 1 }); using (Bitmap screenPixel = new Bitmap(1, 1)) { using (Graphics g = Graphics.FromImage(screenPixel)) { g.CopyFromScreen(area.Left, area.Top, 0, 0, screenPixel.Size); } var color = screenPixel.GetPixel(0, 0); return (color.R, color.G, color.B); } }); } } }