原文:2019-11-29-WPF-模拟触摸设备

title author date CreateTime categories
WPF 模拟触摸设备
lindexi
2019-11-29 08:47:53 +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-11-29-WPF-模拟触摸设备的更多相关文章

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

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

  2. 2019.7.29 NOIP模拟测试10 反思总结【T2补全】

    这次意外考得不错…但是并没有太多厉害的地方,因为我只是打满了暴力[还没去推T3] 第一题折腾了一个小时,看了看时间先去写第二题了.第二题尝试了半天还是只写了三十分的暴力,然后看到第三题是期望,本能排斥 ...

  3. 2019.11.29 Mysql的数据操作

    为名为name的表增加数据(插入所有字段) insert into name values(1,‘张三’,‘男’,20); 为名为name的表增加数据(插入部分字段) insert into name ...

  4. 2019.11.29 SAP SMTP郵件服務器配置 發送端 QQ郵箱

    今天群裏的小夥伴問了如何配置郵件的問題,隨自己在sap裏面配置了一個 1.    RZ10配置參數 a)       参数配置前,先导入激活版本 执行完毕后返回 b)      输入参数文件DEFAU ...

  5. 2019/11/8 CSP模拟

    T1 药品实验 内网#4803 由概率定义,有\[a + b + c = 0\] 变形得到\[1 - b = a + c\] 根据题意有\[p_i = a p _{i - 1} + b p_i + c ...

  6. 2019/11/1 CSP模拟

    写在前面的反思 该拿的部分分还是得拿完啊,因为懒+动作慢没有写最后一道题的菊花图和链的情况,其实这两个点并不难.. 虽然只有\(10pts\),但是已经足够往上爬一截了啊,额外的\(10pts\)在今 ...

  7. 2019.10.29 csp-s模拟测试93 反思总结

    T1: 求出前缀和,三维偏序O(nlog2n)CDQ 二维其实就可以 #include<iostream> #include<cstdio> #include<cstri ...

  8. 2019.10.29 csp-s模拟测试92 反思总结

    今天快乐的墨雨笙因为什么而几乎爆零了呢? 顾此失彼+不会对拍+无脑的复杂度 今天高兴的墨雨笙又因为什么调了一个下午呢? 不明题意+不想范围+板子低级错误 R.I.P. T1: //唉 //害怕TLE, ...

  9. 2019.9.29 csp-s模拟测试55 反思总结

    不咕咕咕是一种美德[大雾] 头一次体会到爆肝写题解??? 这次考试我们没赶上,是后来掐着时间每个人自己考的.我最后的分数能拿到152…熟悉的一题AC两题爆炸. 强烈吐槽出题人起名走心 T1联: 发现每 ...

  10. pycharm+anaconda在Mac上的配置方法 2019.11.29

    内心os: 听人说,写blog是加分项,那他就不是浪费时间的事儿了呗 毕竟自己菜还是留下来东西来自己欣赏吧 Mac小电脑上进行python数据开发环境的配置 首先下载Anaconda,一个超好用的数据 ...

随机推荐

  1. java基础(12):构造方法、this、super

    1. 构造方法 我们对封装已经有了基本的了解,接下来我们来看一个新的问题,依然以Person为例,由于Person中的属性都被private了,外界无法直接访问属性,必须对外提供相应的set和get方 ...

  2. 面试官常问的Nginx的那几个问题?

    什么是Nginx? Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代 ...

  3. 易优CMS:【小白学标签】之empty的基础用法

    [基础用法] 名称:empty 功能:判断某个变量是否为空,可以嵌套到任何标签里面使用,比如:channel.type等 语法: {eyou:empty name='$eyou.field.seo_t ...

  4. 基于token机制鉴权架构

    常见的鉴权方式有两种,一种是基于session,另一种是基于token方式的鉴权,我们来浅谈一下两种 鉴权方式的区别. 两种鉴权方式对比 session 安全性:session是基于cookie进行用 ...

  5. javafx笔记----非javafx线程Platform.runLater赋值不生效情况

    Platform.runLater(() -> { // }); Platform.runLater一些情况下没有赋值到fx页面上 采用task方式 Task<SB> task = ...

  6. Event事件、进程池与线程池、协程

    目录 Event事件 进程池与线程池 多线程爬取梨视频 协程 协程目的 gevent TCP服务端socket套接字实现协程 Event事件 用来控制线程的执行 出现e.wait(),就会把这个线程设 ...

  7. liteos MMU(十八)

    1. 概述 1.1 基本概念 MMU全称"Memory Management Unit",顾名思义就是"内存管理单元". 1.2 运作机制 建立页表描述符号表, ...

  8. [Go] gocron源码阅读-go语言中的切片接口和类型综合

    // getCommands func getCommands() []cli.Command { command := cli.Command{ Name: "web", Usa ...

  9. 7.3 DStream操作

    一.Spark Streaming工作机制 在Spark Streaming中,会有一个组件Receiver,作为一个长期运行的task跑在一个Executor上: 每个Receiver都会负责一个i ...

  10. python的gRPC示例

    参考URL: https://segmentfault.com/a/1190000015220713?utm_source=channel-hottest gRPC 是一个高性能.开源和通用的 RPC ...