133 lines
5.0 KiB
C#
133 lines
5.0 KiB
C#
|
/* This software is licensed by the MIT License, see LICENSE file */
|
|||
|
/* Copyright © 2024-2025 Gregory Lirent */
|
|||
|
|
|||
|
#if WINIPC_UA_SERVER
|
|||
|
using System.Drawing;
|
|||
|
using System.Runtime.InteropServices;
|
|||
|
using System.Text;
|
|||
|
using WinIPC.Models;
|
|||
|
|
|||
|
namespace WinIPC.Utils
|
|||
|
{
|
|||
|
public class WindowScanner
|
|||
|
{
|
|||
|
[StructLayout(LayoutKind.Explicit)]
|
|||
|
internal struct RECT
|
|||
|
{
|
|||
|
[FieldOffset(0)]
|
|||
|
public int Left;
|
|||
|
[FieldOffset(4)]
|
|||
|
public int Top;
|
|||
|
[FieldOffset(8)]
|
|||
|
public int Right;
|
|||
|
[FieldOffset(12)]
|
|||
|
public int Bottom;
|
|||
|
[FieldOffset(0)]
|
|||
|
public int X;
|
|||
|
[FieldOffset(4)]
|
|||
|
public int Y;
|
|||
|
}
|
|||
|
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
|||
|
|
|||
|
[DllImport("user32.dll")]
|
|||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|||
|
internal static extern bool GetCursorPos(out RECT lpPoint);
|
|||
|
[DllImport("user32.dll")]
|
|||
|
private static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
|
|||
|
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|||
|
private static extern int GetWindowTextLength(IntPtr hWnd);
|
|||
|
[DllImport("user32.dll")]
|
|||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|||
|
private static extern bool GetClientRect(IntPtr hwnd, out RECT lpRect);
|
|||
|
[DllImport("user32.dll")]
|
|||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|||
|
internal static extern bool ScreenToClient(IntPtr hWnd, ref RECT lpPoint);
|
|||
|
[DllImport("user32.dll")]
|
|||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|||
|
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
|||
|
[DllImport("user32.dll")]
|
|||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|||
|
private static extern bool IsWindowVisible(IntPtr hWnd);
|
|||
|
[DllImport("user32.dll")]
|
|||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|||
|
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
|
|||
|
[DllImport("user32.dll", SetLastError = true)]
|
|||
|
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|||
|
[DllImport("user32.dll")]
|
|||
|
private static extern IntPtr GetForegroundWindow();
|
|||
|
[DllImport("user32.dll")]
|
|||
|
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
|
|||
|
[DllImport("user32.dll", SetLastError = true)]
|
|||
|
public static extern long GetWindowLongPtr(IntPtr hWnd, int nIndex);
|
|||
|
private bool GetWindowInfo(ref WindowInfo data, IntPtr hwnd)
|
|||
|
{
|
|||
|
int length = GetWindowTextLength(hwnd);
|
|||
|
|
|||
|
if (length > 0)
|
|||
|
{
|
|||
|
var sb = new StringBuilder(length + 1);
|
|||
|
GetWindowText(hwnd, sb, sb.Capacity);
|
|||
|
data.Title = sb.ToString();
|
|||
|
|
|||
|
if (GetCursorPos(out RECT pt) && ScreenToClient(hwnd, ref pt))
|
|||
|
{
|
|||
|
data.CursorPosition = new Models.Point { X = pt.X, Y = pt.Y };
|
|||
|
}
|
|||
|
|
|||
|
if (GetWindowRect(hwnd, out RECT 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 (GetClientRect(hwnd, out RECT 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;
|
|||
|
}
|
|||
|
public async Task<IEnumerable<WindowInfo>> ScanAsync(ushort max = 0)
|
|||
|
{
|
|||
|
if (max == 0) max = UInt16.MaxValue;
|
|||
|
|
|||
|
return await Task.Run(() =>
|
|||
|
{
|
|||
|
var foreground = GetForegroundWindow();
|
|||
|
List<WindowInfo> container = new();
|
|||
|
|
|||
|
EnumWindows(delegate (IntPtr hwnd, IntPtr lParam)
|
|||
|
{
|
|||
|
if (container.Count >= max) return false;
|
|||
|
|
|||
|
if (IsWindowVisible(hwnd))
|
|||
|
{
|
|||
|
WindowInfo data = new();
|
|||
|
|
|||
|
data.Hwnd = hwnd.ToInt32();
|
|||
|
|
|||
|
if ((data.ThreadId = (int)GetWindowThreadProcessId(hwnd, out uint pid)) != 0)
|
|||
|
{
|
|||
|
data.Pid = (int)pid;
|
|||
|
|
|||
|
if (GetWindowInfo(ref data, hwnd))
|
|||
|
{
|
|||
|
data.IsActive = foreground.ToInt32() == data.Hwnd;
|
|||
|
container.Add(data);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return true;
|
|||
|
}, IntPtr.Zero);
|
|||
|
|
|||
|
return container;
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|