2020-08-05 17:32:49 +08:00
|
|
|
using System;
|
2020-08-15 22:21:08 +08:00
|
|
|
using System.Runtime.InteropServices;
|
2020-08-05 17:32:49 +08:00
|
|
|
|
2020-10-15 21:25:17 +08:00
|
|
|
namespace VoiDPlugins.TouchEmu
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-28 02:33:48 +08:00
|
|
|
public static class Touch
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-15 22:21:08 +08:00
|
|
|
private static IntPtr _penHandle;
|
|
|
|
private static POINTER_TYPE_INFO[] pointer;
|
|
|
|
private static uint _pointerId;
|
|
|
|
private static IntPtr _sourceDevice;
|
2020-08-05 17:32:49 +08:00
|
|
|
|
2020-08-28 02:33:48 +08:00
|
|
|
public static unsafe void Init()
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-28 02:33:48 +08:00
|
|
|
NativeMethods.GetPointerDevices(out uint count, null);
|
|
|
|
POINTER_DEVICE_INFO[] pointerDevices = new POINTER_DEVICE_INFO[count];
|
|
|
|
NativeMethods.GetPointerDevices(out count, pointerDevices);
|
|
|
|
for (int i = 0; i < count; i++)
|
2020-08-15 22:21:08 +08:00
|
|
|
{
|
2020-08-28 02:33:48 +08:00
|
|
|
var device = pointerDevices[i];
|
2020-08-15 22:21:08 +08:00
|
|
|
if (device.pointerDeviceType == POINTER_DEVICE_TYPE.EXTERNAL_PEN ||
|
|
|
|
device.pointerDeviceType == POINTER_DEVICE_TYPE.INTEGRATED_PEN)
|
|
|
|
{
|
|
|
|
_pointerId = (uint)device.startingCursorId;
|
2020-08-28 02:33:48 +08:00
|
|
|
_sourceDevice = new IntPtr(device.device);
|
2020-08-15 22:21:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var _pointerInfo = new POINTER_INFO
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
|
|
|
pointerType = POINTER_INPUT_TYPE.PT_PEN,
|
2020-08-15 22:21:08 +08:00
|
|
|
pointerId = _pointerId,
|
2020-08-05 17:32:49 +08:00
|
|
|
frameId = 0,
|
2020-08-15 22:21:08 +08:00
|
|
|
pointerFlags = POINTER_FLAGS.NONE,
|
2020-08-28 02:33:48 +08:00
|
|
|
sourceDevice = _sourceDevice,
|
|
|
|
hwndTarget = NativeMethods.GetForegroundWindow(),
|
2020-08-05 17:32:49 +08:00
|
|
|
ptPixelLocation = new POINT(),
|
|
|
|
ptPixelLocationRaw = new POINT(),
|
|
|
|
dwTime = 0,
|
2020-08-15 22:21:08 +08:00
|
|
|
historyCount = 0,
|
2020-08-05 17:32:49 +08:00
|
|
|
dwKeyStates = 0,
|
|
|
|
PerformanceCount = 0,
|
|
|
|
ButtonChangeType = POINTER_BUTTON_CHANGE_TYPE.NONE
|
|
|
|
};
|
|
|
|
|
2020-08-15 22:21:08 +08:00
|
|
|
var _penInfo = new POINTER_PEN_INFO
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
|
|
|
pointerInfo = _pointerInfo,
|
|
|
|
pointerFlags = PEN_FLAGS.NONE,
|
2020-08-15 22:21:08 +08:00
|
|
|
penMask = PEN_MASK.PRESSURE,
|
|
|
|
pressure = 512,
|
2020-08-05 17:32:49 +08:00
|
|
|
rotation = 0,
|
|
|
|
tiltX = 0,
|
|
|
|
tiltY = 0
|
|
|
|
};
|
|
|
|
|
2020-08-15 22:21:08 +08:00
|
|
|
pointer = new POINTER_TYPE_INFO[]
|
|
|
|
{
|
|
|
|
new POINTER_TYPE_INFO
|
|
|
|
{
|
|
|
|
type = POINTER_INPUT_TYPE.PT_PEN,
|
|
|
|
penInfo = _penInfo
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-08-05 17:32:49 +08:00
|
|
|
// Retrieve handle to custom pen
|
|
|
|
_penHandle = NativeMethods.CreateSyntheticPointerDevice(POINTER_INPUT_TYPE.PT_PEN, 1, POINTER_FEEDBACK_MODE.INDIRECT);
|
2020-08-15 22:21:08 +08:00
|
|
|
var err = Marshal.GetLastWin32Error();
|
|
|
|
if (err < 0 || _penHandle == IntPtr.Zero)
|
2020-08-28 02:33:48 +08:00
|
|
|
throw new Exception("Failed to create handle.");
|
2020-08-05 17:32:49 +08:00
|
|
|
|
|
|
|
// Notify WindowsInk
|
2020-08-15 22:21:08 +08:00
|
|
|
ClearPointerFlags(POINTER_FLAGS.NEW);
|
2020-08-05 17:32:49 +08:00
|
|
|
Inject();
|
|
|
|
|
|
|
|
// Back to normal state
|
2020-08-15 22:21:08 +08:00
|
|
|
ClearPointerFlags(POINTER_FLAGS.INRANGE | POINTER_FLAGS.PRIMARY);
|
2020-08-05 17:32:49 +08:00
|
|
|
}
|
|
|
|
|
2020-08-15 22:21:08 +08:00
|
|
|
public static void Inject()
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-15 22:21:08 +08:00
|
|
|
if (!NativeMethods.InjectSyntheticPointerInput(_penHandle, pointer, 1))
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-28 02:33:48 +08:00
|
|
|
throw new Exception($"Input injection failed. Reason: {Marshal.GetLastWin32Error()}");
|
2020-08-05 17:32:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-28 02:33:48 +08:00
|
|
|
public static void SetTarget()
|
|
|
|
{
|
|
|
|
pointer[0].penInfo.pointerInfo.hwndTarget = NativeMethods.GetForegroundWindow();
|
|
|
|
}
|
|
|
|
|
2020-08-15 22:21:08 +08:00
|
|
|
public static void SetPosition(POINT point)
|
|
|
|
{
|
|
|
|
pointer[0].penInfo.pointerInfo.ptPixelLocation = point;
|
|
|
|
pointer[0].penInfo.pointerInfo.ptPixelLocationRaw = point;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void SetPressure(uint pressure)
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-15 22:21:08 +08:00
|
|
|
pointer[0].penInfo.pressure = pressure;
|
2020-08-05 17:32:49 +08:00
|
|
|
}
|
|
|
|
|
2020-08-15 22:21:08 +08:00
|
|
|
public static void SetPointerFlags(POINTER_FLAGS flags)
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-15 22:21:08 +08:00
|
|
|
pointer[0].penInfo.pointerInfo.pointerFlags |= flags;
|
2020-08-05 17:32:49 +08:00
|
|
|
}
|
|
|
|
|
2020-08-15 22:21:08 +08:00
|
|
|
public static void UnsetPointerFlags(POINTER_FLAGS flags)
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-15 22:21:08 +08:00
|
|
|
pointer[0].penInfo.pointerInfo.pointerFlags &= ~flags;
|
2020-08-05 17:32:49 +08:00
|
|
|
}
|
|
|
|
|
2020-08-15 22:21:08 +08:00
|
|
|
public static void ClearPointerFlags()
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-15 22:21:08 +08:00
|
|
|
pointer[0].penInfo.pointerInfo.pointerFlags = 0;
|
2020-08-05 17:32:49 +08:00
|
|
|
}
|
|
|
|
|
2020-08-15 22:21:08 +08:00
|
|
|
public static void ClearPointerFlags(POINTER_FLAGS flags)
|
2020-08-05 17:32:49 +08:00
|
|
|
{
|
2020-08-15 22:21:08 +08:00
|
|
|
pointer[0].penInfo.pointerInfo.pointerFlags = flags;
|
2020-08-05 17:32:49 +08:00
|
|
|
}
|
|
|
|
}
|
2020-08-28 02:33:48 +08:00
|
|
|
}
|