diff --git a/BetterGenshinImpact/View/PickerWindow.xaml b/BetterGenshinImpact/View/PickerWindow.xaml
index 1cf76084..2d43c943 100644
--- a/BetterGenshinImpact/View/PickerWindow.xaml
+++ b/BetterGenshinImpact/View/PickerWindow.xaml
@@ -1,37 +1,183 @@
-
+ WindowStartupLocation="CenterScreen"
+ Background="#FF1E1E1E">
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/View/PickerWindow.xaml.cs b/BetterGenshinImpact/View/PickerWindow.xaml.cs
index b7cc0448..20f33cd4 100644
--- a/BetterGenshinImpact/View/PickerWindow.xaml.cs
+++ b/BetterGenshinImpact/View/PickerWindow.xaml.cs
@@ -7,71 +7,160 @@ 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 IntPtr PickCaptureTarget(IntPtr hWnd)
+ public bool PickCaptureTarget(IntPtr hWnd,out IntPtr PickedWindow)
{
new WindowInteropHelper(this).Owner = hWnd;
ShowDialog();
-
- return ((CapturableWindow?)WindowList.SelectedItem)?.Handle ?? IntPtr.Zero;
+ 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();
+
User32.EnumWindows((hWnd, lParam) =>
{
- // ignore invisible windows
- if (!User32.IsWindowVisible(hWnd))
+ if (!User32.IsWindowVisible(hWnd) || wih.Handle == hWnd)
return true;
- // ignore untitled windows
var title = new StringBuilder(1024);
_ = User32.GetWindowText(hWnd, title, title.Capacity);
if (string.IsNullOrWhiteSpace(title.ToString()))
return true;
- // ignore me
- if (wih.Handle == hWnd)
- return true;
-
_ = User32.GetWindowThreadProcessId(hWnd, out var processId);
-
- // ignore by process name
var process = Process.GetProcessById((int)processId);
if (_ignoreProcesses.Contains(process.ProcessName.ToLower()))
return true;
- WindowList.Items.Add(new CapturableWindow
+ // 获取窗口图标
+ var icon = GetWindowIcon((IntPtr)hWnd);
+
+ windows.Add(new CapturableWindow
{
Handle = (IntPtr)hWnd,
- Name = $"{title} ({process.ProcessName}.exe)"
+ 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();
}
}
diff --git a/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs
index 604cfed6..bb7613d6 100644
--- a/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs
+++ b/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs
@@ -139,29 +139,42 @@ public partial class HomePageViewModel : ObservableObject, INavigationAware, IVi
private void OnStartCaptureTest()
{
var picker = new PickerWindow();
- var hWnd = picker.PickCaptureTarget(new WindowInteropHelper(UIDispatcherHelper.MainWindow).Handle);
- if (hWnd != IntPtr.Zero)
+
+ if (picker.PickCaptureTarget(new WindowInteropHelper(UIDispatcherHelper.MainWindow).Handle, out var hWnd))
{
- var captureWindow = new CaptureTestWindow();
- captureWindow.StartCapture(hWnd, Config.CaptureMode.ToCaptureMode());
- captureWindow.Show();
+ if (hWnd != IntPtr.Zero)
+ {
+ var captureWindow = new CaptureTestWindow();
+ captureWindow.StartCapture(hWnd, Config.CaptureMode.ToCaptureMode());
+ captureWindow.Show();
+ }
+ else
+ {
+ MessageBox.Error("选择的窗体句柄为空");
+ }
}
+
+
}
[RelayCommand]
private void OnManualPickWindow()
{
var picker = new PickerWindow();
- var hWnd = picker.PickCaptureTarget(new WindowInteropHelper(UIDispatcherHelper.MainWindow).Handle);
- if (hWnd != IntPtr.Zero)
+ if(picker.PickCaptureTarget(new WindowInteropHelper(UIDispatcherHelper.MainWindow).Handle,out var hWnd))
{
- _hWnd = hWnd;
- Start(hWnd);
- }
- else
- {
- MessageBox.Error("选择的窗体句柄为空!");
+ if (hWnd != IntPtr.Zero)
+ {
+ _hWnd = hWnd;
+ Start(hWnd);
+ }
+ else
+ {
+ MessageBox.Error("选择的窗体句柄为空!");
+ }
+
}
+
}
[RelayCommand]
@@ -181,8 +194,13 @@ public partial class HomePageViewModel : ObservableObject, INavigationAware, IVi
var hWnd = SystemControl.FindGenshinImpactHandle();
if (hWnd == IntPtr.Zero)
{
- if (Config.GenshinStartConfig.LinkedStartEnabled && !string.IsNullOrEmpty(Config.GenshinStartConfig.InstallPath))
+ if (Config.GenshinStartConfig.LinkedStartEnabled)
{
+ if (string.IsNullOrEmpty(Config.GenshinStartConfig.InstallPath))
+ {
+ MessageBox.Error("没有找到原神的安装路径");
+ return;
+ }
hWnd = await SystemControl.StartFromLocalAsync(Config.GenshinStartConfig.InstallPath);
if (hWnd != IntPtr.Zero)
{
diff --git a/View/PickerWindow.xaml b/View/PickerWindow.xaml
new file mode 100644
index 00000000..0519ecba
--- /dev/null
+++ b/View/PickerWindow.xaml
@@ -0,0 +1 @@
+
\ No newline at end of file