using XFEExtension.NetCore.InputSimulator.Native; namespace XFEExtension.NetCore.InputSimulator; /// 连接已安装的 UMDF 虚拟 HID 驱动;驱动缺失或不可用时报告错误,不自动安装。 /// 输入会话独占,同一时间只能有一个控制器。支持六个普通键及八个修饰键;不回退到软件注入。 public sealed class DriverBackend : IInputBackend { private readonly IDriverTransport transport; private readonly object sync = new(); private bool disposed; /// 连接已安装的驱动。使用 DriverDeployment 显式检测和安装驱动。 public DriverBackend() : this(new DriverTransport()) { } internal DriverBackend(IDriverTransport transport) { this.transport = transport; try { var info = transport.Query(); if (!DriverProtocol.IsCompatible(info)) throw new NotSupportedException("已安装的 XFE 驱动与本 DLL 协议不匹配,请更新驱动后重新启动应用。"); } catch { transport.Dispose(); throw; } } /// public string Name => "XFE UMDF HID driver"; /// public bool SupportsUnicodeText => false; /// public void SendKey(ScanCode key, bool isKeyUp) { var command = DriverCommand.Create(1); command.Code = HidKeyMapping.GetUsage(key); command.Flags = isKeyUp ? 1u : 0u; Send(command); } /// public void SendUnicode(char codeUnit, bool isKeyUp) => throw new NotSupportedException("HID 驱动不支持 Unicode 文本注入。请用 InputKeys 按当前键盘布局输入可映射的字符。"); /// public void MoveMouse(int x, int y, bool absolute, bool virtualDesktop) { InputValidation.Coordinates(x, y, absolute, virtualDesktop); if (absolute) throw new NotSupportedException("当前 HID 驱动提供相对鼠标移动,不支持绝对定位。"); lock (sync) { CheckDisposed(); do { var command = DriverCommand.Create(3); command.X = Math.Clamp(x, -32767, 32767); command.Y = Math.Clamp(y, -32767, 32767); transport.Send(command); x -= command.X; y -= command.Y; } while (x != 0 || y != 0); } } /// public void SendMouseButton(MouseButton button, bool isKeyUp) { InputValidation.Button(button); var command = DriverCommand.Create(2); command.Code = (uint)button; command.Flags = isKeyUp ? 1u : 0u; Send(command); } /// public void ScrollMouse(int delta, bool horizontal) { if (delta % 120 != 0) throw new ArgumentOutOfRangeException(nameof(delta), "HID 滚轮以一格为单位,delta 必须是 120 的整数倍。"); lock (sync) { CheckDisposed(); for (var ticks = delta / 120; ticks != 0;) { var command = DriverCommand.Create(4); command.Flags = horizontal ? 1u : 0u; command.Delta = Math.Clamp(ticks, -127, 127); transport.Send(command); ticks -= command.Delta; } } } private void Send(DriverCommand command) { lock (sync) { CheckDisposed(); transport.Send(command); } } private void CheckDisposed() => ObjectDisposedException.ThrowIf(disposed, this); /// 请求驱动释放全部输入并关闭会话;进程异常退出后,驱动会在约三秒无心跳时尝试释放。 public void Dispose() { lock (sync) { if (disposed) return; disposed = true; try { transport.Reset(); } finally { transport.Dispose(); } } } }