title author date CreateTime categories
WPF 模拟触摸设备
lindexi
2019-05-12 16:19:32 +0800
2019-5-11 17:2:6 +0800
WPF

在 WPF 中触摸只是框架的一层,可以通过代码模拟触摸

创建一个类继承 TouchDevice 然后重写 GetTouchPoint 和 GetIntermediateTouchPoints 方法,可以在这个类里面通过调用 ReportDown 等方法模拟触摸的按下和移动

最简单的实现请看下面代码

    public class BurnerkadelWallnadarli : TouchDevice
{
/// <inheritdoc />
public BurnerkadelWallnadarli(int deviceId, Window window) : base(deviceId)
{
Window = window;
} /// <summary>
/// 触摸点
/// </summary>
public Point Position { set; get; } /// <summary>
/// 触摸大小
/// </summary>
public Size Size { set; get; } public void Down()
{
TouchAction = TouchAction.Down; if (!IsActive)
{
SetActiveSource(PresentationSource.FromVisual(Window)); Activate();
ReportDown();
}
else
{
ReportDown();
}
} public void Move()
{
TouchAction = TouchAction.Move; ReportMove();
} public void Up()
{
TouchAction = TouchAction.Up; ReportUp();
Deactivate();
} private Window Window { get; } private TouchAction TouchAction { set; get; } /// <inheritdoc />
public override TouchPoint GetTouchPoint(IInputElement relativeTo)
{
return new TouchPoint(this, Position, new Rect(Position, Size), TouchAction);
} /// <inheritdoc />
public override TouchPointCollection GetIntermediateTouchPoints(IInputElement relativeTo)
{
return new TouchPointCollection()
{
GetTouchPoint(relativeTo)
};
}
}

在 TouchDevice 里面,调用触摸按下和移动等的方法是没有传入参数的,在框架是通过 GetTouchPoint 拿到当前用户触摸的点

在按下的时候需要激活,激活的时候需要传入一个 PresentationSource 在框架通过这个值进行命中测试找到触摸按下的点是按到哪个元素

使用的时候只需要创建 BurnerkadelWallnadarli 然后调用对应的按下移动等方法就可以了,因为在构造的时候传入了窗口,所以在按下等事件可以通过传入的窗口进行命中测试找到按下的元素,从元素触发路由事件

大概的调用顺序是这样的,在触摸的第一个事件是按下,在按下的时候使用下面代码

SetActiveSource(PresentationSource.FromVisual(Window));

Activate();
ReportDown();

在 SetActiveSource 会将传入的 PresentationSource 设置在本地的字段 _activeSource 这样可以在拿到点的时候调用

在调用 Activate 方法会调用一次 UpdateDirectlyOver 这个方法调用 GetTouchPoint 传入一个空参数,用来判断当前是否命中到元素,一般都是没有命中的,需要到 ReportDown 的时候才可能命中元素。在 Activate 会将当前的 TouchDevice 加入到 TouchDevice._activeDevices 这个静态字段里面,如果刚好这时的静态字段只有一个元素,那么就设置当前的触摸设备是主触摸设备

设置触摸设备是主触摸设备是因为在触摸的时候如果用户是多个手指触摸,一个手指对应一个触摸设备,所以第一个手指对应主触摸设备

调用 ReportDown 会先设置本地字段 _isDown 为 true 然后调用 UpdateDirectlyOver 方法更新当前按下点到的元素,然后调用 RaiseTouchDown 方法在当前点到的元素触摸触摸按下的路由事件,可以看到此时的路由事件是不需要再获取当前的触摸点,因为只是在点到的元素触摸事件,如果这个元素需要知道当前的触摸点,只需要在方法使用参数的 e.GetTouchPoint 方法就可以重新拿到触摸点。因为获取触摸点方法是可以重写的,所以第一次获取的用于命中测试的触摸点可以和元素收到触摸事件获取的触摸点返回不同的点

只需要拿到了对应的元素就可以在元素触发事件,从触摸到事件请看WPF 触摸到事件

调用 ReportMove 移动的方法也是差不多,首先通过 UpdateDirectlyOver 找到命中测试的元素,然后触发路由事件。如果元素不关注触摸点击的点就不需要再次调用获取触摸点方法

那么 UpdateDirectlyOver 是如何进行命中测试的?首先通过获取触摸点方法拿到传入空参数时的触摸点,这时相对的应该是窗口的坐标。通过 TouchDevice.LocalHitTest 方法拿到命中测试的元素,在底层调用的是 MouseDevice.LocalHitTest 方法

所以可以通过上面定义的类模拟触摸,只需要创建出来,然后调用对应的方法就可以,如下面的代码就模拟了按下和移动

var burnerkadelWallnadarli = new BurnerkadelWallnadarli(1, this);

await Task.Delay(1000);
burnerkadelWallnadarli.Down(); await Task.Delay(1000);
// 设置当前触摸点
burnerkadelWallnadarli.Move();

通过这个方法模拟触摸可以走原有的 WPF 触摸命中测试,也能走路由事件

关于 WPF 的触摸到事件请看 WPF 触摸到事件

本文用到的代码放在 github

2019-5-12-WPF-模拟触摸设备的更多相关文章

  1. 2019.8.12 NOIP模拟测试18 反思总结

    写个博客总是符合要求的对吧 回来以后第一次悄悄参加考试,昨天全程围观… 然后喜提爆炸120分wwwwwwwww T1用了全机房最慢的写法,导致改掉死循环T掉的一个点以后还是死活过不了最后一个点.T2全 ...

  2. 【2019.8.12 慈溪模拟赛 T1】钥匙(key)(暴力DP)

    暴力\(DP\) 这题做法很多,有\(O(n^2)\)的,有\(O(n^2logn)\)的,还有徐教练的\(O(nlogn)\)的,甚至还有\(bzt\)的二分+线段树优化建图的费用流. 我懒了点,反 ...

  3. 【2019.8.12 慈溪模拟赛 T2】汪哥图(wang)(前缀和)

    森林 考虑到题目中给出条件两点间至多只有一条路径. 就可以发现,这是一个森林. 而森林有一个很有用的性质. 考虑对于一棵树,点数-边数=\(1\). 因此对于一个森林,点数-边数=连通块个数. 所以, ...

  4. 2019/11/12 CSP模拟赛&&考前小总结

    写在前面的总结 离联赛只有几天了,也马上就要回归文化课了. 有点舍不得,感觉自己的水平刚刚有点起色,却又要被抓回文化课教室了,真想在机房再赖几天啊. 像19/11/11那场的简单题,自己还是能敲出一些 ...

  5. 2019-11-29-WPF-模拟触摸设备

    原文:2019-11-29-WPF-模拟触摸设备 title author date CreateTime categories WPF 模拟触摸设备 lindexi 2019-11-29 08:47 ...

  6. 2019-11-29-WPF-测试触摸设备发送触摸按下和抬起不成对

    原文:2019-11-29-WPF-测试触摸设备发送触摸按下和抬起不成对 title author date CreateTime categories WPF 测试触摸设备发送触摸按下和抬起不成对 ...

  7. 2019-7-15-WPF-测试触摸设备发送触摸按下和抬起不成对

    title author date CreateTime categories WPF 测试触摸设备发送触摸按下和抬起不成对 lindexi 2019-7-15 9:3:51 +0800 2019-0 ...

  8. 通过解读 WPF 触摸源码,分析 WPF 插拔设备触摸失效的问题(问题篇)

    在 .NET Framework 4.7 以前,WPF 程序的触摸处理是基于操作系统组件但又自成一套的,这其实也为其各种各样的触摸失效问题埋下了伏笔.再加上它出现得比较早,触摸失效问题也变得更加难以解 ...

  9. WPF 插拔触摸设备触摸失效

    原文:WPF 插拔触摸设备触摸失效 最近使用 WPF 程序,在不停插拔触摸设备会让 WPF 程序触摸失效.通过分析 WPF 源代码可以找到 WPF 触摸失效的原因. 在 Windows 会将所有的 H ...

随机推荐

  1. C++临时对象的生命期

    class Test{ public: Test(int a):m_int(a){ printf("this is Test(%d) ctor\n", m_int); } ~Tes ...

  2. 全球首个百万IOPS云盘即将商业化 阿里云推出超高性能云盘ESSD

    近日,在经过近半年的上线公测后,阿里云全球首个跨入IOPS百万时代的云盘——ESSD即将迎来商业化,单盘IOPS高达100万,这是阿里云迄今为止性能最强的企业级块存储服务. 搭配ECS云服务器使用, ...

  3. TCPThree_C杯 Day1

    题解 或 正规题解 已经很详细,不再赘述. 跟着wjx打代码,不怕卡题. 忘开long long智障错误第四次左偏树

  4. odoo 内置协议说明列表

    odoo 内置协议说明列表 在以下目录. /odoo/odoo/addons/base/models/ir_module.py license = fields.Selection([ ('GPL-2 ...

  5. 【LeetCode】90.Subsets II

    Subsets II Given a collection of integers that might contain duplicates, nums, return all possible s ...

  6. poj 1845 【数论:逆元,二分(乘法),拓展欧几里得,费马小定理】

    POJ 1845 题意不说了,网上一大堆.此题做了一天,必须要整理一下了. 刚开始用费马小定理做,WA.(poj敢说我代码WA???)(以下代码其实都不严谨,按照数据要求A是可以等于0的,那么结果自然 ...

  7. nodeJs学习-03 GET数据请求,js拆解/querystring/url

    原生JS解析参数: const http = require('http'); http.createServer(function(req,res){ var GET = {}; //接收数据容器 ...

  8. 云原生生态周报 Vol. 8 | Gartner 发布云原生趋势

    业界要闻 Gartner 发布云原生基础设施未来的八大趋势:权威分析机构 Gartner 在对 2020 年技术趋势的展望当中指出:“预计2020年所有领先的容器管理软件均内置服务融合技术,到2022 ...

  9. @codeforces - 1214F@ Employment

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 有 m 个城市围成一个圆环,编号为 1~m. 某公司有 n 个职 ...

  10. python 直接if判断和is not None的区别

    tmpName = ''if tmpName: print tmpName #没有输出if tmpName is not None: print tmpName #有输出,是空行