Initial commit

This commit is contained in:
2026-09-18 14:26:02 +03:00 Unverified
commit 171f94414d
22 changed files with 1340 additions and 0 deletions
+184
View File
@@ -0,0 +1,184 @@
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
/// <summary>
/// Retrieves a list of structs representing all visible top-level windows with titles and native WinUI 3 icons.
/// </summary>
public async Task<List<WindowInfo>> GetVisibleWindowsAsync(bool onlyVisible)
{
var windowList = new List<WindowInfo>();
var handles = new List<IntPtr>();
// 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<SoftwareBitmapSource> 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;
}
}
}