/// <summary> /// 触摸消息转WPF事件 /// 此方案只支持Touch,没有Stylus事件。同时Touch与Mouse事件被独立开了。--此方案有缺陷,但能勉强使用。TODO 模拟Stylus事件触发 /// </summary> /// <param name="window"></param> /// <param name="input"></param> private static void FakeTouchInputToWindow(Window window, TouchNativeMethods.TOUCHINPUT input) { // 相对的是没有处理 DPI 的屏幕坐标 // 因为是 物理屏幕坐标的像素的百分之一表示,需要除 100 计算像素 var screenLocation = new Point(input.X / 100.0, input.Y / 100.0); var wpfLocation = TransformToWpfPoint(screenLocation, window); var sizeInScreen = new Size(input.CxContact / 100.0, input.CyContact / 100.0); var wpfSize = TransformToWpfSize(sizeInScreen, window); //获取触摸设备信息 var device = MessageTouchDeviceHelper.GetDevice(window, input.DwID); if (!device.IsActive && input.DwFlags.HasFlag(TouchNativeMethods.TOUCHEVENTF.TOUCHEVENTF_DOWN)) { device.Position = wpfLocation; device.Size = wpfSize; device.Down(); } else if (device.IsActive && input.DwFlags.HasFlag(TouchNativeMethods.TOUCHEVENTF.TOUCHEVENTF_MOVE)) { device.Position = wpfLocation; device.Size = wpfSize; device.Move(); } else if (device.IsActive && input.DwFlags.HasFlag(TouchNativeMethods.TOUCHEVENTF.TOUCHEVENTF_UP)) { device.Position = wpfLocation; device.Size = wpfSize; device.Up(); MessageTouchDeviceHelper.Remove(device); } }
private static void FakeTouchInpuToPenContext1(Window window, TouchNativeMethods.TOUCHINPUT input, int inputCount) { //InputManager.Current.PostProcessInput InputManager.Current //var postProcessInputEvent = typeof(InputManager).GetEvent("_postProcessInput", BindingFlags.NonPublic | BindingFlags.Instance).GetRaiseMethod(true); ; //var privateInputEventArgsProperty = typeof(InputManager).GetField("_processInputEventArgs", BindingFlags.NonPublic | BindingFlags.Instance); //var inputEventArgs = privateInputEventArgsProperty.GetValue(InputManager.Current) as ProcessInputEventArgs; //if (inputEventArgs == null) //{ // inputEventArgs = Activator.CreateInstance(typeof(ProcessInputEventArgs)) as ProcessInputEventArgs; // privateInputEventArgsProperty.SetValue(InputManager.Current, inputEventArgs); //} //postProcessInputEvent.Invoke(InputManager.Current, new object[1]{ inputEventArgs }); }
/// <summary> /// 模拟触摸输入(PenContext) /// 因触摸数据无法转换、会多余一份Mouse事件。此方案废弃 /// </summary> /// <param name="window"></param> /// <param name="input"></param> /// <param name="inputCount"></param> private static void FakeTouchInputToPenContext0(Window window, TouchNativeMethods.TOUCHINPUT input, int inputCount) { Assembly wpfAssembly = typeof(TabletDevice).Assembly; var wispLogicType = wpfAssembly.GetType("System.Windows.Input.StylusWisp.WispLogic"); var wispLogicConstructorInfos = wispLogicType.GetConstructors(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance); var wispLogicConstructorInfo = wispLogicConstructorInfos[0]; var wispLogic = wispLogicConstructorInfo.Invoke(new object[] { InputManager.Current }); var penContextsConstructorInfo = wpfAssembly.GetTypes().Where(i => i.FullName.Contains("PenContexts")).ToList()[0]. GetConstructors(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance).First(); var penContextsInstance = penContextsConstructorInfo.Invoke(new object[2] { wispLogic, PresentationSource.FromVisual(window) }); var penContextsValue = penContextsInstance.GetType().GetField("_contexts", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(penContextsInstance) as object[]; if (penContextsValue == null || penContextsValue.Length == 0) { penContextsInstance.GetType().GetMethod("Enable", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(penContextsInstance, null); penContextsValue = penContextsInstance.GetType().GetField("_contexts", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(penContextsInstance) as object[]; } if (penContextsValue == null || penContextsValue.Length == 0) { //uint index = 1; //penContextsInstance.GetType().GetMethod("AddContext", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(penContextsInstance, new object[1] { index }); //penContextsValue = penContextsInstance.GetType().GetField("_contexts", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(penContextsInstance) as object[]; //以上无法添加 } object penContext = null; if (penContextsValue != null && penContextsValue.Length > 0) { penContext = penContextsValue[0]; _lastPenContext = penContext; } else { if (_lastPenContext == null) { return; } penContext = _lastPenContext; } var tabletDeviceId = (int)penContext.GetType().GetProperty("TabletDeviceId", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(penContext); //可能因触摸数据没有转换,此处调用但是WPF层好像无效 penContextsValue.GetType().GetMethod("OnPenDown", BindingFlags.NonPublic | BindingFlags.Instance)?.Invoke(penContextsValue, new object[5] { penContext, tabletDeviceId, input.DwID, new int[3], input.DwTime }); //并且input输入无法转换 }
/// <summary> /// 处理窗口消息 /// </summary> /// <param name="window"></param> /// <param name="msg"></param> /// <param name="wParam"></param> /// <param name="lParam"></param> /// <param name="handled"></param> private static void HandleWindowProc(Window window, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == TouchNativeMethods.WM_TOUCH) { var inputCount = wParam.ToInt32() & 0xffff; var inputs = new TouchNativeMethods.TOUCHINPUT[inputCount]; if (TouchNativeMethods.GetTouchInputInfo(lParam, inputCount, inputs, TouchNativeMethods.TouchInputSize)) { for (int i = 0; i < inputCount; i++) { var input = inputs[i]; //FakeTouchInputToPenContext0(window, input, inputCount); //FakeTouchInputToPenContext1(window, input, inputCount); FakeTouchInputToWindow(window, input); } } TouchNativeMethods.CloseTouchInputHandle(lParam); handled = true; } }
/// <summary> /// 待完成 /// </summary> /// <param name="window"></param> /// <param name="input"></param> /// <param name="inputCount"></param> private static void FakeTouchInputToPenContext1(Window window, TouchNativeMethods.TOUCHINPUT input, int inputCount) { var stylusLogicType = typeof(TabletDevice).Assembly.GetType("System.Windows.Input.StylusLogic"); var stylusLogic = stylusLogicType.GetProperty("CurrentStylusLogic", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null); if (stylusLogic.GetType().FullName.Contains("WispLogic")) { var wispLogic = stylusLogic; //var wispTabletList = wispLogic.GetType().GetProperty("CurrentStylusDevice", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(wispLogic); if (!registeredPresentationSources.Contains(PresentationSource.FromVisual(window))) { //先注销 wispLogic.GetType().GetMethod("UnRegisterHwndForInput", BindingFlags.NonPublic | BindingFlags.Instance) .Invoke(wispLogic, new object[1] { (HwndSource)PresentationSource.FromVisual(window) }); //初始化PenContext等 //只能注册一次 wispLogic.GetType().GetMethod("RegisterHwndForInput", BindingFlags.NonPublic | BindingFlags.Instance) .Invoke(wispLogic, new object[2] { InputManager.Current, PresentationSource.FromVisual(window) }); registeredPresentationSources.Add(PresentationSource.FromVisual(window)); } var penContextsObject = wispLogic.GetType().GetMethod("GetPenContextsFromHwnd", BindingFlags.NonPublic | BindingFlags.Instance) .Invoke(wispLogic, new[] { PresentationSource.FromVisual(window) }); var penContextsValue = penContextsObject.GetType().GetField("_contexts", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(penContextsObject) as object[]; if (penContextsValue == null || penContextsValue.Length == 0) { penContextsObject.GetType().GetMethod("Enable", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(penContextsObject, null); penContextsValue = penContextsObject.GetType().GetField("_contexts", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(penContextsObject) as object[]; } if (penContextsValue == null || penContextsValue.Length == 0) { //uint index = 1; //penContextsInstance.GetType().GetMethod("AddContext", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(penContextsInstance, new object[1] { index }); //penContextsValue = penContextsInstance.GetType().GetField("_contexts", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(penContextsInstance) as object[]; //以上无法添加 } object penContext = null; if (penContextsValue != null && penContextsValue.Length > 0) { penContext = penContextsValue[0]; _lastPenContext = penContext; } else { if (_lastPenContext == null) { return; } penContext = _lastPenContext; } var tabletDeviceId = (int)penContext.GetType().GetProperty("TabletDeviceId", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(penContext); //因触摸数据无法转换,此处调用但是WPF层好像无效 penContextsValue.GetType().GetMethod("OnPenDown", BindingFlags.NonPublic | BindingFlags.Instance)?.Invoke(penContextsValue, new object[5] { penContext, tabletDeviceId, input.DwID, new int[3], input.DwTime }); //并且input输入无法转换 } }