Files
better-genshin-impact/BetterGenshinImpact/View/PickerWindow.xaml.cs
2025-01-06 18:35:11 +08:00

173 lines
5.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BetterGenshinImpact.Helpers.DpiAwareness;
using System;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using Vanara.PInvoke;
using System.Windows.Media;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
using System.Runtime.InteropServices;
namespace BetterGenshinImpact.View;
public partial class PickerWindow : Window
{
private static readonly string[] _ignoreProcesses = ["applicationframehost", "shellexperiencehost", "systemsettings", "winstore.app", "searchui"];
private bool _isSelected = false;
public PickerWindow()
{
InitializeComponent();
this.InitializeDpiAwareness();
Loaded += OnLoaded;
}
public class CapturableWindow
{
public string Name { get; set; }
public string ProcessName { get; set; }
public IntPtr Handle { get; set; }
public ImageSource Icon { get; set; }
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
FindWindows();
}
public bool PickCaptureTarget(IntPtr hWnd,out IntPtr PickedWindow)
{
new WindowInteropHelper(this).Owner = hWnd;
ShowDialog();
if(!_isSelected)
{
PickedWindow = IntPtr.Zero;
return false;
}
PickedWindow = ((CapturableWindow?)WindowList.SelectedItem)?.Handle ?? IntPtr.Zero;
return true;
}
private unsafe void FindWindows()
{
var wih = new WindowInteropHelper(this);
var windows = new List<CapturableWindow>();
User32.EnumWindows((hWnd, lParam) =>
{
if (!User32.IsWindowVisible(hWnd) || wih.Handle == hWnd)
return true;
var title = new StringBuilder(1024);
_ = User32.GetWindowText(hWnd, title, title.Capacity);
if (string.IsNullOrWhiteSpace(title.ToString()))
return true;
_ = User32.GetWindowThreadProcessId(hWnd, out var processId);
var process = Process.GetProcessById((int)processId);
if (_ignoreProcesses.Contains(process.ProcessName.ToLower()))
return true;
// 获取窗口图标
var icon = GetWindowIcon((IntPtr)hWnd);
windows.Add(new CapturableWindow
{
Handle = (IntPtr)hWnd,
Name = title.ToString(),
ProcessName = process.ProcessName,
Icon = icon
});
return true;
}, IntPtr.Zero);
WindowList.ItemsSource = windows;
}
private ImageSource GetWindowIcon(IntPtr hWnd)
{
try
{
const int ICON_BIG = 1; // WM_GETICON large icon constant
const int ICON_SMALL = 0; // WM_GETICON small icon constant
const int GCL_HICON = -14; // GetClassLong index for icon
// 尝试获取窗口大图标
var iconHandle = User32.SendMessage(hWnd, User32.WindowMessage.WM_GETICON, (IntPtr)ICON_BIG, IntPtr.Zero);
if (iconHandle == IntPtr.Zero)
{
// 尝试获取窗口小图标
iconHandle = User32.SendMessage(hWnd, User32.WindowMessage.WM_GETICON, (IntPtr)ICON_SMALL, IntPtr.Zero);
}
if (iconHandle == IntPtr.Zero)
{
// 尝试获取窗口类图标
iconHandle = User32.GetClassLong(hWnd, GCL_HICON);
}
if (iconHandle != IntPtr.Zero)
{
return Imaging.CreateBitmapSourceFromHIcon(
iconHandle,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
}
catch (Exception ex)
{
Debug.WriteLine($"获取窗口图标失败: {ex.Message}");
}
// 如果获取失败返回一个默认图标或null
return null;
}
private bool IsGenshinWindow(string windowName)
{
// 判断是否包含原神相关的进程名 TODO更加健壮的判断
return windowName == "原神";
}
private bool AskIsThisGenshinImpact(string windowName)
{
var res = MessageBox.Question(
$"""
这看起来不像是原神,确定要选择这个窗口吗?
当前选择的窗口:{windowName}
""",
"确认选择",
MessageBoxButton.YesNo,
MessageBoxResult.No
);
return res == MessageBoxResult.Yes;
}
private void WindowsOnMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var selectedWindow = WindowList.SelectedItem as CapturableWindow;
if (selectedWindow == null) return;
// 如果不是原神窗口,询问用户是否确认
if (!IsGenshinWindow(selectedWindow.Name))
{
if (!AskIsThisGenshinImpact(selectedWindow.Name))
{
return;
}
}
_isSelected = true;
Close();
}
}
public struct CapturableWindow
{
public string Name { get; set; }
public IntPtr Handle { get; set; }
}