From bda91816d4a67c49d53abfb1aa45ac20a67448a7 Mon Sep 17 00:00:00 2001 From: DarkFlameMaster <1004452714@qq.com> Date: Tue, 30 Dec 2025 17:43:33 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20KeyMouseHook=E7=9B=B8=E5=85=B3=20(#2588)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core/Script/Dependence/KeyMouseHook.cs | 170 +++++++++++------- .../Core/Script/EngineExtend.cs | 5 +- 2 files changed, 104 insertions(+), 71 deletions(-) diff --git a/BetterGenshinImpact/Core/Script/Dependence/KeyMouseHook.cs b/BetterGenshinImpact/Core/Script/Dependence/KeyMouseHook.cs index 5f492f28..0c1ec1d7 100644 --- a/BetterGenshinImpact/Core/Script/Dependence/KeyMouseHook.cs +++ b/BetterGenshinImpact/Core/Script/Dependence/KeyMouseHook.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Windows.Forms; using BetterGenshinImpact.Core.Monitor; +using BetterGenshinImpact.GameTask; using Gma.System.MouseKeyHook; using Microsoft.ClearScript; using Microsoft.Extensions.Logging; @@ -41,6 +42,74 @@ public class KeyMouseHook: IDisposable private readonly ILogger _logger = App.GetLogger(); + /// + /// 统一处理回调函数执行过程中的异常 + /// + /// 捕获到的异常 + /// 事件类型描述 + private void HandleCallbackException(Exception ex, string eventType) + { + if (ex is ScriptEngineException scriptEx) + { + _logger.LogError("执行{eventType}JS回调时发生错误:{scriptEx.Message},清除所有回调",eventType, scriptEx.Message); + _logger.LogDebug("{scriptEx}",scriptEx); + } + else + { + _logger.LogError("执行{eventType}回调时发生错误:{ex.Message},清除所有回调,如果此异常出现在JS脚本结束时,请在JS脚本结束前手动调用Dispose()方法",eventType,ex.Message); + _logger.LogDebug("{ex}",ex); + } + + Dispose(); + } + + /// + /// 将全局屏幕坐标转换为游戏窗口局部坐标 + /// + /// 全局X坐标 + /// 全局Y坐标 + /// 游戏窗口局部坐标(X, Y),转换失败时返回(-1, -1) + private (int X, int Y) ConvertToLocalCoordinates(int globalX, int globalY) + { + try + { + // 检查TaskContext是否已初始化 + if (!TaskContext.Instance().IsInitialized) + { + _logger.LogError("TaskContext未初始化,无法获取游戏窗口信息"); + return (-1, -1); + } + + var gameHandle = TaskContext.Instance().GameHandle; + if (gameHandle == IntPtr.Zero) + { + _logger.LogError("游戏窗口句柄无效,无法获取游戏窗口位置"); + return (-1, -1); + } + + // 获取游戏窗口捕获区域 + var captureRect = SystemControl.GetCaptureRect(gameHandle); + + // 检查捕获区域是否有效 + if (captureRect.Width <= 0 || captureRect.Height <= 0) + { + _logger.LogError("获取的游戏窗口捕获区域无效,宽度或高度为0"); + return (-1, -1); + } + + // 计算局部坐标 + int localX = globalX - captureRect.Left; + int localY = globalY - captureRect.Top; + + return (localX, localY); + } + catch (Exception ex) + { + _logger.LogError(ex, "转换鼠标坐标时发生错误"); + return (-1, -1); + } + } + public KeyMouseHook() { // 初始化事件处理程序 @@ -57,16 +126,10 @@ public class KeyMouseHook: IDisposable { callback.InvokeAsFunction(args.KeyData.ToString()); } - catch (InvalidOperationException ex) when (ex.Message.Contains("V8 object has been released")) - { - _logger.LogDebug("V8对象已释放,清除所有回调"); - RemoveAllListeners(); - return; - } catch (Exception ex) { - _logger.LogError(ex, "执行键盘按下事件回调时发生错误"); - // 忽略单个回调执行异常,不影响其他回调 + HandleCallbackException(ex, "键盘按下事件"); + return; } } @@ -77,17 +140,12 @@ public class KeyMouseHook: IDisposable { callback.InvokeAsFunction(args.KeyCode.ToString()); } - catch (InvalidOperationException ex) when (ex.Message.Contains("V8 object has been released")) - { - _logger.LogDebug("V8对象已释放,清除所有回调"); - RemoveAllListeners(); - return; - } catch (Exception ex) { - _logger.LogError(ex, "执行键盘按下事件回调时发生错误"); - // 忽略单个回调执行异常,不影响其他回调 + HandleCallbackException(ex, "键盘按下事件"); + return; } + } }; @@ -104,16 +162,10 @@ public class KeyMouseHook: IDisposable { callback.InvokeAsFunction(args.KeyData.ToString()); } - catch (InvalidOperationException ex) when (ex.Message.Contains("V8 object has been released")) - { - _logger.LogDebug("V8对象已释放,清除所有回调"); - RemoveAllListeners(); - return; - } catch (Exception ex) { - _logger.LogError(ex, "执行键盘释放事件回调时发生错误"); - // 忽略单个回调执行异常,不影响其他回调 + HandleCallbackException(ex, "键盘释放事件"); + return; } } @@ -124,16 +176,10 @@ public class KeyMouseHook: IDisposable { callback.InvokeAsFunction(args.KeyCode.ToString()); } - catch (InvalidOperationException ex) when (ex.Message.Contains("V8 object has been released")) - { - _logger.LogDebug("V8对象已释放,清除所有回调"); - RemoveAllListeners(); - return; - } catch (Exception ex) { - _logger.LogError(ex, "执行键盘释放事件回调时发生错误"); - // 忽略单个回调执行异常,不影响其他回调 + HandleCallbackException(ex, "键盘释放事件"); + return; } } }; @@ -143,22 +189,19 @@ public class KeyMouseHook: IDisposable // 创建回调列表的副本,避免迭代期间修改集合导致异常 var mouseDownCallbacksCopy = new List(_mouseDownCallbacks); + // 转换为局部坐标 + var (localX, localY) = ConvertToLocalCoordinates(args.X, args.Y); + foreach (var callback in mouseDownCallbacksCopy) { try { - callback.InvokeAsFunction(args.Button.ToString(), args.X, args.Y); - } - catch (InvalidOperationException ex) when (ex.Message.Contains("V8 object has been released")) - { - _logger.LogDebug("V8对象已释放,清除所有回调"); - RemoveAllListeners(); - return; + callback.InvokeAsFunction(args.Button.ToString(), localX, localY); } catch (Exception ex) { - _logger.LogError(ex, "执行鼠标按下事件回调时发生错误"); - // 忽略单个回调执行异常,不影响其他回调 + HandleCallbackException(ex, "鼠标按下事件"); + return; } } }; @@ -168,22 +211,19 @@ public class KeyMouseHook: IDisposable // 创建回调列表的副本,避免迭代期间修改集合导致异常 var mouseUpCallbacksCopy = new List(_mouseUpCallbacks); + // 转换为局部坐标 + var (localX, localY) = ConvertToLocalCoordinates(args.X, args.Y); + foreach (var callback in mouseUpCallbacksCopy) { try { - callback.InvokeAsFunction(args.Button.ToString(), args.X, args.Y); - } - catch (InvalidOperationException ex) when (ex.Message.Contains("V8 object has been released")) - { - _logger.LogDebug("V8对象已释放,清除所有回调"); - RemoveAllListeners(); - return; + callback.InvokeAsFunction(args.Button.ToString(), localX, localY); } catch (Exception ex) { - _logger.LogError(ex, "执行鼠标释放事件回调时发生错误"); - // 忽略单个回调执行异常,不影响其他回调 + HandleCallbackException(ex, "鼠标释放事件"); + return; } } }; @@ -194,6 +234,9 @@ public class KeyMouseHook: IDisposable // 创建回调列表的副本,避免迭代期间修改集合导致异常 var mouseMoveCallbacksCopy = new List(_mouseMoveCallbacks); + // 转换为局部坐标 + var (localX, localY) = ConvertToLocalCoordinates(args.X, args.Y); + foreach (var callback in mouseMoveCallbacksCopy) { try @@ -209,23 +252,17 @@ public class KeyMouseHook: IDisposable // 如果时间差大于等于间隔时间,则执行回调 if (timeSpan.TotalMilliseconds >= interval) { - callback.InvokeAsFunction(args.X, args.Y); + callback.InvokeAsFunction(localX, localY); // 更新上次调用时间 _lastMouseMoveCallbackTimes[callback] = now; } } } } - catch (InvalidOperationException ex) when (ex.Message.Contains("V8 object has been released")) - { - _logger.LogDebug("V8对象已释放,清除所有回调"); - RemoveAllListeners(); - return; - } catch (Exception ex) { - _logger.LogError(ex, "执行鼠标移动事件回调时发生错误"); - // 忽略单个回调执行异常,不影响其他回调 + HandleCallbackException(ex, "鼠标移动事件"); + return; } } }; @@ -235,22 +272,19 @@ public class KeyMouseHook: IDisposable // 创建回调列表的副本,避免迭代期间修改集合导致异常 var mouseWheelCallbacksCopy = new List(_mouseWheelCallbacks); + // 转换为局部坐标 + var (localX, localY) = ConvertToLocalCoordinates(args.X, args.Y); + foreach (var callback in mouseWheelCallbacksCopy) { try { - callback.InvokeAsFunction(args.Delta, args.X, args.Y); - } - catch (InvalidOperationException ex) when (ex.Message.Contains("V8 object has been released")) - { - _logger.LogDebug("V8对象已释放,清除所有回调"); - RemoveAllListeners(); - return; + callback.InvokeAsFunction(args.Delta, localX, localY); } catch (Exception ex) { - _logger.LogError(ex, "执行鼠标滚轮事件回调时发生错误"); - // 忽略单个回调执行异常,不影响其他回调 + HandleCallbackException(ex, "鼠标滚轮事件"); + return; } } }; diff --git a/BetterGenshinImpact/Core/Script/EngineExtend.cs b/BetterGenshinImpact/Core/Script/EngineExtend.cs index 998744a4..c5baad3d 100644 --- a/BetterGenshinImpact/Core/Script/EngineExtend.cs +++ b/BetterGenshinImpact/Core/Script/EngineExtend.cs @@ -35,7 +35,6 @@ public class EngineExtend engine.AddHostObject("file", new LimitedFile(workDir)); // 限制文件访问 engine.AddHostObject("http", new Http()); // 限制文件访问 engine.AddHostObject("notification", new Notification()); - engine.AddHostObject("keyMouseHook", new KeyMouseHook()); // 任务调度器 engine.AddHostObject("dispatcher", new Dispatcher(config)); @@ -71,8 +70,8 @@ public class EngineExtend engine.AddHostType("AutoDomainParam", typeof(AutoDomainParam)); engine.AddHostType("AutoFightParam", typeof(AutoFightParam)); - - + //鼠标回调 + engine.AddHostType("KeyMouseHook", typeof(KeyMouseHook)); // 添加C#的类型 engine.AddHostType(typeof(Task));