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());
+ }
}
}
-
}