Files
better-genshin-impact/BetterGenshinImpact/GameTask/SystemControl.cs
mfkvfhpdx 91a0e771b9 修改调度器任务和部分独立任务失去焦点时,强制切换回游戏窗口,如果用常规的方式无法激活窗口,则第10次会尝试最小化所有窗口后激活游戏。 (#1185)
* 修改调度器任务和部分独立任务失去焦点时,强制切换回游戏窗口,如果用常规的方式无法激活窗口,则第10次会尝试最小化所有窗口后激活游戏。

* 去除未引入的类引用

* 修正战斗结束后,大概率打开队伍界面的问题

* 修复有些电脑上因未知原因,战斗0秒打断

* 把失焦激活放入了设置-通用设置-其他设置中,默认关闭。暂停恢复时,重置移动的起始时间,防止因暂停而导致超时放弃任务。
2025-02-25 00:01:33 +08:00

263 lines
7.7 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 System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Vanara.PInvoke;
namespace BetterGenshinImpact.GameTask;
public class SystemControl
{
public static nint FindGenshinImpactHandle()
{
return FindHandleByProcessName("YuanShen", "GenshinImpact", "Genshin Impact Cloud Game");
}
public static async Task<nint> StartFromLocalAsync(string path)
{
// 直接exe启动
Process.Start(new ProcessStartInfo(path)
{
UseShellExecute = true,
Arguments = TaskContext.Instance().Config.GenshinStartConfig.GenshinStartArgs,
WorkingDirectory = Path.GetDirectoryName(path)
});
for (var i = 0; i < 5; i++)
{
var handle = FindGenshinImpactHandle();
if (handle != 0)
{
await Task.Delay(2333);
handle = FindGenshinImpactHandle();
await Task.Delay(2577);
return handle;
}
await Task.Delay(5577);
}
return FindGenshinImpactHandle();
}
public static bool IsGenshinImpactActiveByProcess()
{
var name = GetActiveProcessName();
return name is "YuanShen" or "GenshinImpact" or "Genshin Impact Cloud Game";
}
public static bool IsGenshinImpactActive()
{
var hWnd = User32.GetForegroundWindow();
return hWnd == TaskContext.Instance().GameHandle;
}
public static nint GetForegroundWindowHandle()
{
return (nint)User32.GetForegroundWindow();
}
public static nint FindHandleByProcessName(params string[] names)
{
foreach (var name in names)
{
var pros = Process.GetProcessesByName(name);
if (pros.Length is not 0)
{
return pros[0].MainWindowHandle;
}
}
return 0;
}
public static nint FindHandleByWindowName()
{
var handle = (nint)User32.FindWindow("UnityWndClass", "原神");
if (handle != 0)
{
return handle;
}
handle = (nint)User32.FindWindow("UnityWndClass", "Genshin Impact");
if (handle != 0)
{
return handle;
}
handle = (nint)User32.FindWindow("Qt5152QWindowIcon", "云·原神");
if (handle != 0)
{
return handle;
}
return 0;
}
public static string? GetActiveProcessName()
{
try
{
var hWnd = User32.GetForegroundWindow();
_ = User32.GetWindowThreadProcessId(hWnd, out var pid);
var p = Process.GetProcessById((int)pid);
return p.ProcessName;
}
catch
{
return null;
}
}
public static Process? GetProcessByHandle(nint hWnd)
{
try
{
_ = User32.GetWindowThreadProcessId(hWnd, out var pid);
var p = Process.GetProcessById((int)pid);
return p;
}
catch (Exception ex)
{
Debug.WriteLine(ex);
return null;
}
}
/// <summary>
/// 获取窗口位置
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
public static RECT GetWindowRect(nint hWnd)
{
// User32.GetWindowRect(hWnd, out var windowRect);
DwmApi.DwmGetWindowAttribute<RECT>(hWnd, DwmApi.DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, out var windowRect);
return windowRect;
}
/// <summary>
/// 游戏本身分辨率获取
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
public static RECT GetGameScreenRect(nint hWnd)
{
User32.GetClientRect(hWnd, out var clientRect);
return clientRect;
}
/// <summary>
/// GetWindowRect or GetGameScreenRect
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
public static RECT GetCaptureRect(nint hWnd)
{
var windowRect = GetWindowRect(hWnd);
var gameScreenRect = GetGameScreenRect(hWnd);
var left = windowRect.Left;
var top = windowRect.Top + windowRect.Height - gameScreenRect.Height;
var right = left + gameScreenRect.Width;
var bottom = top + gameScreenRect.Height;
return new RECT(left, top, right, bottom);
}
public static void ActivateWindow(nint hWnd)
{
User32.ShowWindow(hWnd, ShowWindowCommand.SW_RESTORE);
User32.SetForegroundWindow(hWnd);
}
public static void ActivateWindow()
{
if (!TaskContext.Instance().IsInitialized)
{
throw new Exception("请先启动BetterGI");
}
ActivateWindow(TaskContext.Instance().GameHandle);
}
public static void FocusWindow(nint hWnd)
{
if (User32.IsWindow(hWnd))
{
_ = User32.SendMessage(hWnd, User32.WindowMessage.WM_SYSCOMMAND, User32.SysCommand.SC_RESTORE, 0);
_ = User32.SetForegroundWindow(hWnd);
while (User32.IsIconic(hWnd))
{
continue;
}
_ = User32.BringWindowToTop(hWnd);
_ = User32.SetActiveWindow(hWnd);
}
}
public static void MinimizeAndActivateWindow(nint hWnd)
{
HWND hShell = User32.FindWindow("Shell_TrayWnd", null);
User32.SendMessage(hShell, 0x0111, (IntPtr)419, IntPtr.Zero);
Thread.Sleep(500);
FocusWindow(hWnd);
}
public static void RestoreWindow(nint hWnd)
{
if (User32.IsWindow(hWnd))
{
_ = User32.SendMessage(hWnd, User32.WindowMessage.WM_SYSCOMMAND, User32.SysCommand.SC_RESTORE, 0);
_ = User32.SetForegroundWindow(hWnd);
if (User32.IsIconic(hWnd))
{
_ = User32.ShowWindow(hWnd, ShowWindowCommand.SW_RESTORE);
}
_ = User32.BringWindowToTop(hWnd);
_ = User32.SetActiveWindow(hWnd);
}
}
public static bool IsFullScreenMode(IntPtr hWnd)
{
if (hWnd == IntPtr.Zero)
{
return false;
}
var exStyle = User32.GetWindowLong(hWnd, User32.WindowLongFlags.GWL_EXSTYLE);
return (exStyle & (int)User32.WindowStylesEx.WS_EX_TOPMOST) != 0;
}
// private static void StartFromLauncher(string path)
// {
// // 通过launcher启动
// var process = Process.Start(new ProcessStartInfo(path) { UseShellExecute = true });
// Thread.Sleep(1000);
// // 获取launcher窗口句柄
// var hWnd = FindHandleByProcessName("launcher");
// var rect = GetWindowRect(hWnd);
// var dpiScale = Helpers.DpiHelper.ScaleY;
// // 对于launcher启动按钮的位置时固定的在launcher窗口的右下角
// Thread.Sleep(1000);
// Simulation.MouseEvent.Click((int)((float)rect.right * dpiScale) - (rect.Width / 5), (int)((float)rect.bottom * dpiScale) - (rect.Height / 8));
// }
//
// private static void StartCloudYaunShen(string path)
// {
// // 通过launcher启动
// var process = Process.Start(new ProcessStartInfo(path) { UseShellExecute = true });
// Thread.Sleep(10000);
// // 获取launcher窗口句柄
// var hWnd = FindHandleByProcessName("Genshin Impact Cloud Game");
// var rect = GetWindowRect(hWnd);
// var dpiScale = Helpers.DpiHelper.ScaleY;
// // 对于launcher启动按钮的位置时固定的在launcher窗口的右下角
// Simulation.MouseEvent.Click(rect.right - (rect.Width / 6), rect.bottom - (rect.Height / 13 * 3));
// // TODO点完之后有个15s的倒计时好像不处理也没什么问题直接睡个20s吧
// Thread.Sleep(20000);
// }
}