.Net Framework下InkCanvas屏蔽触摸鼠标仅响应触控笔问题求解
问题根因
WPF输入路由顺序为Stylus事件 -> Touch事件 -> Mouse事件,你在PreviewTouchDown标记事件已处理时,触摸操作触发的StylusMove等事件已经完成了临时墨迹的渲染,只有当后续逻辑判定输入为触摸时才会删除墨迹,因此出现临时线条残留。另外你仅拦截了Down类事件,未拦截Move类事件,也会导致触摸滑动过程中持续生成临时墨迹。
可行解决方案
两种方案均完全兼容.NET Framework 4.8,不需要依赖Core版本控件或Islands组件。
方案1:自定义InkCanvas控件(最稳定)
直接继承InkCanvas重写所有输入相关的方法,从根源过滤非触控笔输入:
public class StylusOnlyInkCanvas : InkCanvas { protected override void OnStylusDown(StylusDownEventArgs e) { if (e.StylusDevice?.TabletDevice.Type == TabletDeviceType.Stylus) { base.OnStylusDown(e); } else { e.Handled = true; } } protected override void OnStylusMove(StylusEventArgs e) { if (e.StylusDevice?.TabletDevice.Type != TabletDeviceType.Stylus) { e.Handled = true; return; } base.OnStylusMove(e); } protected override void OnStylusUp(StylusEventArgs e) { if (e.StylusDevice?.TabletDevice.Type != TabletDeviceType.Stylus) { e.Handled = true; return; } base.OnStylusUp(e); } protected override void OnTouchDown(TouchEventArgs e) { e.Handled = true; } protected override void OnTouchMove(TouchEventArgs e) { e.Handled = true; } protected override void OnTouchUp(TouchEventArgs e) { e.Handled = true; } protected override void OnMouseDown(MouseButtonEventArgs e) { var isStylusMouse = e.StylusDevice?.TabletDevice.Type == TabletDeviceType.Stylus; if (!isStylusMouse) { e.Handled = true; return; } base.OnMouseDown(e); } }
使用方式:直接替换现有XAML中的<InkCanvas>标签为<local:StylusOnlyInkCanvas>即可,不需要额外挂接事件。
方案2:补全现有事件拦截逻辑
如果不想自定义控件,在现有代码基础上补全所有Stylus和Touch路由事件的拦截即可:
// 原有事件基础上新增以下事件处理 private void InkCanvas_PreviewStylusMove(object sender, StylusEventArgs e) { TabletDeviceType? type = e.StylusDevice?.TabletDevice?.Type; if (type == null || type == TabletDeviceType.Touch) e.Handled = true; } private void InkCanvas_PreviewStylusUp(object sender, StylusEventArgs e) { TabletDeviceType? type = e.StylusDevice?.TabletDevice?.Type; if (type == null || type == TabletDeviceType.Touch) e.Handled = true; } private void InkCanvas_PreviewTouchMove(object sender, TouchEventArgs e) { e.Handled = true; } private void InkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) { e.Handled = true; }
使用方式:将新增的4个事件也挂接到你的InkCanvas实例上即可生效。
内容的提问来源于stack exchange,提问作者Marcel Grüger
相关产品推荐
相关产品推荐

