using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using IPClab1.Models; using Microsoft.UI.Xaml.Media.Imaging; using Windows.Graphics.Imaging; namespace IPClab1.Services; public class WindowListService { #region Win32 P/Invoke Declarations private const uint WM_GETICON = 0x007F; private const IntPtr ICON_SMALL = 0; private const IntPtr ICON_BIG = 1; private const IntPtr ICON_SMALL2 = 2; private const int GCLP_HICON = -14; private const int GCLP_HICONSM = -34; private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); [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", CharSet = CharSet.Auto, SetLastError = true)] 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", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", EntryPoint = "GetClassLongPtr", CharSet = CharSet.Auto)] private static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex); [DllImport("user32.dll", EntryPoint = "GetClassLong", CharSet = CharSet.Auto)] private static extern uint GetClassLong32(IntPtr hWnd, int nIndex); [DllImport("user32.dll", SetLastError = true)] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [DllImport("shell32.dll", CharSet = CharSet.Auto)] private static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex); private IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex) { return IntPtr.Size == 8 ? GetClassLongPtr64(hWnd, nIndex) : new IntPtr(GetClassLong32(hWnd, nIndex)); } #endregion /// /// Retrieves a list of structs representing all visible top-level windows with titles and native WinUI 3 icons. /// public async Task> GetVisibleWindowsAsync(bool onlyVisible) { var windowList = new List(); var handles = new List(); // 1. Gather all raw visible window handles that actually contain titles EnumWindows((hWnd, lParam) => { if ((IsWindowVisible(hWnd) || !onlyVisible) && GetWindowTextLength(hWnd) > 0) { handles.Add(hWnd); } return true; }, IntPtr.Zero); // 2. Iterate and async decode titles, process info, and UI image references foreach (var hWnd in handles) { // Fetch window text title cleanly int length = GetWindowTextLength(hWnd); var builder = new StringBuilder(length + 1); GetWindowText(hWnd, builder, builder.Capacity); string title = builder.ToString(); // Fetch numeric process identifier GetWindowThreadProcessId(hWnd, out uint processId); // Fetch and map the icon image synchronously/asynchronously into WinUI structures SoftwareBitmapSource iconSource = await GetWinUi3IconAsync(hWnd); windowList.Add(new WindowInfo { Hwnd = hWnd, ProcessId = processId, WindowTitle = title, IconSource = iconSource }); } return windowList; } private Icon GetIconFromHwnd(IntPtr hWnd) { IntPtr hIcon = SendMessage(hWnd, WM_GETICON, ICON_BIG, IntPtr.Zero); if (hIcon == IntPtr.Zero) hIcon = SendMessage(hWnd, WM_GETICON, ICON_SMALL2, IntPtr.Zero); if (hIcon == IntPtr.Zero) hIcon = GetClassLongPtr(hWnd, GCLP_HICON); if (hIcon == IntPtr.Zero) hIcon = GetClassLongPtr(hWnd, GCLP_HICONSM); if (hIcon != IntPtr.Zero) { try { using var rawIcon = Icon.FromHandle(hIcon); return (Icon)rawIcon.Clone(); } catch { /* Proceed to alternate extraction fallback */ } } try { GetWindowThreadProcessId(hWnd, out uint processId); if (processId != 0) { using var proc = Process.GetProcessById((int)processId); string exePath = proc.MainModule?.FileName; if (!string.IsNullOrEmpty(exePath) && File.Exists(exePath)) { IntPtr hExtracted = ExtractIcon(IntPtr.Zero, exePath, 0); if (hExtracted != IntPtr.Zero && hExtracted != new IntPtr(1)) { using var rawIcon = Icon.FromHandle(hExtracted); return (Icon)rawIcon.Clone(); } } } } catch { /* Protection fallback */ } return null; } private async Task GetWinUi3IconAsync(IntPtr hWnd) { using Icon icon = GetIconFromHwnd(hWnd); if (icon == null) return null; try { using Bitmap bitmap = icon.ToBitmap(); using var stream = new MemoryStream(); bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png); stream.Position = 0; var decoder = await BitmapDecoder.CreateAsync(stream.AsRandomAccessStream()); var softwareBitmap = await decoder.GetSoftwareBitmapAsync( BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied); var source = new SoftwareBitmapSource(); await source.SetBitmapAsync(softwareBitmap); return source; } catch { return null; } } }