CVR Manager 1.0.0

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Exterrata
2026-10-25 02:46:35 -04:00
commit 9bb4f85802
59 changed files with 7913 additions and 0 deletions
+91
View File
@@ -0,0 +1,91 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace CVRManager.Services;
public static class GameWindow
{
const uint WM_SETICON = 0x0080;
const int ICON_SMALL = 0;
const int ICON_BIG = 1;
const int SM_CXICON = 11;
const int SM_CXSMICON = 49;
delegate bool EnumProc(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool EnumWindows(EnumProc proc, IntPtr lParam);
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint pid);
[DllImport("user32.dll")]
static extern bool IsWindowVisible(IntPtr hwnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern int GetClassName(IntPtr hwnd, StringBuilder name, int max);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SendMessageTimeout(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, uint flags, uint timeout, out IntPtr result);
const uint SMTO_ABORTIFHUNG = 2;
[DllImport("user32.dll")]
static extern int GetSystemMetrics(int index);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern uint PrivateExtractIcons(string file, int index, int cx, int cy, IntPtr[] icons, uint[] ids, uint count, uint flags);
static IntPtr FindUnityWindow(int pid)
{
var found = IntPtr.Zero;
var name = new StringBuilder(64);
EnumWindows((hwnd, _) =>
{
GetWindowThreadProcessId(hwnd, out var owner);
if (owner != pid || !IsWindowVisible(hwnd)) return true;
name.Clear();
GetClassName(hwnd, name, name.Capacity);
if (name.ToString() == "UnityWndClass") found = hwnd;
return true;
}, IntPtr.Zero);
return found;
}
static void SetIcons(IntPtr hwnd, string exe)
{
foreach (var (kind, size) in new[] { (ICON_SMALL, GetSystemMetrics(SM_CXSMICON)), (ICON_BIG, GetSystemMetrics(SM_CXICON)) })
{
var icons = new IntPtr[1];
var ids = new uint[1];
if (PrivateExtractIcons(exe, 0, size, size, icons, ids, 1, 0) > 0 && icons[0] != IntPtr.Zero)
SendMessageTimeout(hwnd, WM_SETICON, (IntPtr)kind, icons[0], SMTO_ABORTIFHUNG, 1000, out _);
}
}
public static async Task ApplyIconWhenReadyAsync(Process proc, string exe)
{
if (!OperatingSystem.IsWindows()) return;
try
{
var hwnd = IntPtr.Zero;
for (var i = 0; i < 240 && hwnd == IntPtr.Zero; i++)
{
if (proc.HasExited) return;
hwnd = FindUnityWindow(proc.Id);
if (hwnd == IntPtr.Zero) await Task.Delay(250);
}
if (hwnd == IntPtr.Zero) return;
foreach (var wait in new[] { 0, 3000, 7000, 20000 })
{
await Task.Delay(wait);
if (proc.HasExited) return;
var current = FindUnityWindow(proc.Id);
if (current != IntPtr.Zero) SetIcons(current, exe);
}
}
catch (InvalidOperationException) { }
}
}