196 lines
7.0 KiB
C#
196 lines
7.0 KiB
C#
|
|
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<IEnumerable<Models.WindowInfo>> GetWindows(ushort max = 0, IEnumerable<int>? whitelist = null)
|
|||
|
|
{
|
|||
|
|
if (max == 0) max = UInt16.MaxValue;
|
|||
|
|
if (whitelist == null) whitelist = Array.Empty<int>();
|
|||
|
|
|
|||
|
|
return Task.Run(() =>
|
|||
|
|
{
|
|||
|
|
var foreground = User32Dll.GetForegroundWindow();
|
|||
|
|
List<Models.WindowInfo> 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<Models.WindowInfo>)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);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|