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 partial 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); [LibraryImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static partial bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); [LibraryImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static partial bool IsWindowVisible(IntPtr hWnd); [LibraryImport("user32.dll", EntryPoint = "GetWindowTextW", SetLastError = true)] private static partial int GetWindowText(IntPtr hWnd, [Out] char[] lpString, int nMaxCount); [LibraryImport("user32.dll", EntryPoint = "GetWindowTextLengthW", SetLastError = true)] private static partial int GetWindowTextLength(IntPtr hWnd); [LibraryImport("user32.dll", EntryPoint = "SendMessageW")] private static partial IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [LibraryImport("user32.dll", EntryPoint = "GetClassLongPtrW")] private static partial IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex); [LibraryImport("user32.dll", EntryPoint = "GetClassLongW")] private static partial uint GetClassLong32(IntPtr hWnd, int nIndex); [LibraryImport("user32.dll", SetLastError = true)] private static partial uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [LibraryImport("shell32.dll", EntryPoint = "ExtractIconW", StringMarshalling = StringMarshalling.Utf16)] private static partial 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 var length = GetWindowTextLength(hWnd); var titleBuffer = new char[length + 1]; var actualLength = GetWindowText(hWnd, titleBuffer, titleBuffer.Length); var title = actualLength > 0 ? new string(titleBuffer, 0, actualLength) : string.Empty; // Fetch numeric process identifier GetWindowThreadProcessId(hWnd, out var 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) { var 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; } } }