From 51b38dd15d1a4e29c89a571056547c3555cab64a Mon Sep 17 00:00:00 2001 From: Rxinns <56676566+RxinnotRstar@users.noreply.github.com> Date: Fri, 3 Oct 2025 15:02:13 +0800 Subject: [PATCH] =?UTF-8?q?=EF=BC=88AI=E7=94=9F=E6=88=90=EF=BC=89=E5=85=B3?= =?UTF-8?q?=E4=BA=8E=E4=BF=AE=E5=A4=8Dissue=20#5=20=E7=9A=84=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MapTP.App/MouseProcessor.cs | 229 ++++++++++++++++++++++-------------- 1 file changed, 141 insertions(+), 88 deletions(-) diff --git a/MapTP.App/MouseProcessor.cs b/MapTP.App/MouseProcessor.cs index 611aa06..f01edec 100644 --- a/MapTP.App/MouseProcessor.cs +++ b/MapTP.App/MouseProcessor.cs @@ -1,142 +1,195 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System; using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; namespace MapTP.App { internal class MouseProcessor { + #region ---- Win10 Touch Injection ---- + private const int TOUCH_FEEDBACK_DEFAULT = 0x1; + private const int POINTER_FLAG_NONE = 0x0; + private const int POINTER_FLAG_UPDATE = 0x002; + private const int POINTER_FLAG_DOWN = 0x00010000; + private const int POINTER_FLAG_UP = 0x00040000; + private const int POINTER_FLAG_INRANGE = 0x0002; + private const int POINTER_FLAG_INCONTACT = 0x0004; - #region Win32 - // from https://zhuanlan.zhihu.com/p/626326773 - [StructLayout(LayoutKind.Sequential)] - struct INPUT + private enum POINTER_INPUT_TYPE { - public uint type; - public MOUSEKEYBDHARDWAREINPUT mkhi; + PT_POINTER = 0x00000001, + PT_TOUCH = 0x00000002, + PT_PEN = 0x00000003 } - [StructLayout(LayoutKind.Explicit)] - struct MOUSEKEYBDHARDWAREINPUT + [StructLayout(LayoutKind.Sequential)] + private struct POINTER_TOUCH_INFO { - [FieldOffset(0)] - public HARDWAREINPUT hi; - [FieldOffset(0)] - public KEYBDINPUT ki; - [FieldOffset(0)] - public MOUSEINPUT mi; + public POINTER_INFO pointerInfo; + public uint touchFlags; + public uint touchMask; + public uint orientation; + public uint pressure; } [StructLayout(LayoutKind.Sequential)] - struct KEYBDINPUT + private struct POINTER_INFO { - public ushort wVk; - public ushort wScan; - public uint dwFlags; - public uint time; - public IntPtr dwExtraInfo; + public POINTER_INPUT_TYPE pointerType; + public uint pointerId; + public uint frameId; + public IntPtr targetWindow; + public POINT ptPixelLocation; + public POINT ptPixelLocationRaw; + public uint pointerFlags; + public uint pointerData; + public IntPtr sourceDevice; + public IntPtr hwndTarget; } [StructLayout(LayoutKind.Sequential)] - struct HARDWAREINPUT + private struct POINT + { + public int x, y; + public POINT(int x, int y) { this.x = x; this.y = y; } + } + + [DllImport("user32.dll", SetLastError = true)] + private static extern bool InitializeTouchInjection(uint maxCount, uint dwMode); + + [DllImport("user32.dll", SetLastError = true)] + private static extern bool InjectTouchInput(uint count, [MarshalAs(UnmanagedType.LPArray), In] POINTER_TOUCH_INFO[] contacts); + + private static readonly uint TOUCH_ID = 1; // 我们只用单指 + private static uint frame = 0; + private static bool _available; + + static MouseProcessor() { - public uint uMsg; - public ushort wParamL; - public ushort wParamH; + try + { + // Win10 1607+ 才支持 + var ver = Environment.OSVersion.Version; + if (ver.Major == 10 && ver.Build >= 14393) + _available = InitializeTouchInjection(1, TOUCH_FEEDBACK_DEFAULT); + } + catch { /* 老系统直接放弃 */ } } + #endregion + #region ---- 旧 SendInput 备用 ---- + [StructLayout(LayoutKind.Sequential)] + struct INPUT + { + public uint type; + public MOUSEINPUT mi; + } [StructLayout(LayoutKind.Sequential)] struct MOUSEINPUT { - public int dx; - public int dy; - public uint mouseData; - public uint dwFlags; - public uint time; + public int dx, dy; + public uint mouseData, dwFlags, time; public IntPtr dwExtraInfo; } - [DllImport("user32.dll")] static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize); - - //[DllImport("user32.dll")] - //private static extern int SetCursorPos(int x, int y); + private const uint INPUT_MOUSE = 0; + private const uint MOUSEEVENTF_MOVE = 0x0001, + MOUSEEVENTF_ABSOLUTE = 0x8000, + MOUSEEVENTF_VIRTUALDESK = 0x4000, + MOUSEEVENTF_LEFTDOWN = 0x0002, + MOUSEEVENTF_LEFTUP = 0x0004; #endregion + + /// + /// 把绝对像素坐标注入成指针事件 + /// public void MoveCursor(int x, int y) { - //SetCursorPos(x, y); - INPUT[] _input = new INPUT[1]; - _input[0] = new INPUT + if (_available) { - type = 0, // INPUT_MOUSE - mkhi = new MOUSEKEYBDHARDWAREINPUT + var ti = new POINTER_TOUCH_INFO(); + ti.pointerInfo.pointerType = POINTER_INPUT_TYPE.PT_TOUCH; + ti.pointerInfo.pointerId = TOUCH_ID; + ti.pointerInfo.frameId = ++frame; + ti.pointerInfo.ptPixelLocation = new POINT(x, y); + ti.pointerInfo.ptPixelLocationRaw = new POINT(x, y); + ti.pointerInfo.pointerFlags = POINTER_FLAG_UPDATE | + POINTER_FLAG_INRANGE | + POINTER_FLAG_INCONTACT; + ti.pressure = 320; // 0-1024,随意 + ti.orientation = 90; + ti.touchMask = 0x00000004; // TOUCH_MASK_PRESSURE + InjectTouchInput(1, new[] { ti }); + } + else + { + // 老系统回退 + var inp = new INPUT { + type = INPUT_MOUSE, mi = new MOUSEINPUT { dx = x, dy = y, mouseData = 0, - dwFlags = 0x8000 | 0x0001 | 0x4000, // MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVEMENT | MOUSEEVENTF_VIRTUALDESK - time = 0 // Windows will provide this + dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK, + time = 0 } - } - }; - SendInput((uint)1, _input, Marshal.SizeOf(typeof(INPUT))); - return; - + }; + SendInput(1, new[] { inp }, Marshal.SizeOf()); + } } public void MouseDown() { - INPUT[] _input = new INPUT[1]; - _input[0] = new INPUT + if (_available) { - type = 0, // INPUT_MOUSE - mkhi = new MOUSEKEYBDHARDWAREINPUT + var ti = new POINTER_TOUCH_INFO(); + ti.pointerInfo.pointerType = POINTER_INPUT_TYPE.PT_TOUCH; + ti.pointerInfo.pointerId = TOUCH_ID; + ti.pointerInfo.frameId = ++frame; + ti.pointerInfo.pointerFlags = POINTER_FLAG_DOWN | + POINTER_FLAG_INRANGE | + POINTER_FLAG_INCONTACT; + ti.pressure = 512; + ti.orientation = 90; + ti.touchMask = 0x00000004; + InjectTouchInput(1, new[] { ti }); + } + else + { + var inp = new INPUT { - mi = new MOUSEINPUT - { - dx = 0, - dy = 0, - mouseData = 0, - dwFlags = 0x0002, // MOUSEEVENTF_LEFTDOWN - time = 0 // Windows will provide this - } - } - }; - SendInput((uint)1, _input, Marshal.SizeOf(typeof(INPUT))); - return; + type = INPUT_MOUSE, + mi = new MOUSEINPUT { dwFlags = MOUSEEVENTF_LEFTDOWN } + }; + SendInput(1, new[] { inp }, Marshal.SizeOf()); + } } public void MouseUp() { - INPUT[] _input = new INPUT[1]; - _input[0] = new INPUT + if (_available) { - type = 0, // INPUT_MOUSE - mkhi = new MOUSEKEYBDHARDWAREINPUT + var ti = new POINTER_TOUCH_INFO(); + ti.pointerInfo.pointerType = POINTER_INPUT_TYPE.PT_TOUCH; + ti.pointerInfo.pointerId = TOUCH_ID; + ti.pointerInfo.frameId = ++frame; + ti.pointerInfo.pointerFlags = POINTER_FLAG_UP; + ti.pressure = 0; + ti.orientation = 90; + ti.touchMask = 0x00000004; + InjectTouchInput(1, new[] { ti }); + } + else + { + var inp = new INPUT { - mi = new MOUSEINPUT - { - dx = 0, - dy = 0, - mouseData = 0, - dwFlags = 0x0004, // MOUSEEVENTF_LEFTUP - time = 0 // Windows will provide this - } - } - }; - SendInput((uint)1, _input, Marshal.SizeOf(typeof(INPUT))); - return; - } - - public MouseProcessor() - { + type = INPUT_MOUSE, + mi = new MOUSEINPUT { dwFlags = MOUSEEVENTF_LEFTUP } + }; + SendInput(1, new[] { inp }, Marshal.SizeOf()); + } } } - }