原文: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 等方法模拟触摸的按下和移动

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

  1. public class BurnerkadelWallnadarli : TouchDevice
  2. {
  3. /// <inheritdoc />
  4. public BurnerkadelWallnadarli(int deviceId, Window window) : base(deviceId)
  5. {
  6. Window = window;
  7. }
  8.  
  9. /// <summary>
  10. /// 触摸点
  11. /// </summary>
  12. public Point Position { set; get; }
  13.  
  14. /// <summary>
  15. /// 触摸大小
  16. /// </summary>
  17. public Size Size { set; get; }
  18.  
  19. public void Down()
  20. {
  21. TouchAction = TouchAction.Down;
  22.  
  23. if (!IsActive)
  24. {
  25. SetActiveSource(PresentationSource.FromVisual(Window));
  26.  
  27. Activate();
  28. ReportDown();
  29. }
  30. else
  31. {
  32. ReportDown();
  33. }
  34. }
  35.  
  36. public void Move()
  37. {
  38. TouchAction = TouchAction.Move;
  39.  
  40. ReportMove();
  41. }
  42.  
  43. public void Up()
  44. {
  45. TouchAction = TouchAction.Up;
  46.  
  47. ReportUp();
  48. Deactivate();
  49. }
  50.  
  51. private Window Window { get; }
  52.  
  53. private TouchAction TouchAction { set; get; }
  54.  
  55. /// <inheritdoc />
  56. public override TouchPoint GetTouchPoint(IInputElement relativeTo)
  57. {
  58. return new TouchPoint(this, Position, new Rect(Position, Size), TouchAction);
  59. }
  60.  
  61. /// <inheritdoc />
  62. public override TouchPointCollection GetIntermediateTouchPoints(IInputElement relativeTo)
  63. {
  64. return new TouchPointCollection()
  65. {
  66. GetTouchPoint(relativeTo)
  67. };
  68. }
  69. }

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

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

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

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

  1. SetActiveSource(PresentationSource.FromVisual(Window));
  2.  
  3. Activate();
  4. 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 方法

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

  1. var burnerkadelWallnadarli = new BurnerkadelWallnadarli(1, this);
  2.  
  3. await Task.Delay(1000);
  4. burnerkadelWallnadarli.Down();
  5.  
  6. await Task.Delay(1000);
  7. // 设置当前触摸点
  8. 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. C# ICloneable,shallow clone,deep clone.

    [Serializable] public class Person:ICloneable { public string Name { get; set; } public int Id { get ...

  2. python处理sqlserver数据库的返回数据

    上代码: import SqlHelper.MSSQL as MS import pandas as pd if __name__ == '__main__': #连接数据库 ms = MS.MSSQ ...

  3. 【2019年版】如何向SAP公司提交Message?

    [2019年版]如何向SAP公司提交Message? 1,浏览器里输入如下网址: ,出现如下界面, 2,点击 'Visit the SAP Support Portal' 按钮.进入如下界面,去菜单M ...

  4. IOS系统在Safari安装ipa文件

    配置点击下载的地址 itms-services://?action=download-manifest&url= "plist文件路径"plist文件配置 IIS网站配置要 ...

  5. Discuz 数据库各表的作用

    pre_common_addon 插件扩展中心服务商表 pre_common_admincp_cmenu 后台管理面板,自定义常用菜单表 pre_common_admincp_group 后台团队职务 ...

  6. [20190910]索引分支块中TERM使用什么字符表示.txt

    [20190910]索引分支块中TERM使用什么字符表示.txt --//做索引块转储,一些root,分支节点出现TERM,从来没有关注使用字符表示,简单探究看看. 1.环境:SCOTT@test01 ...

  7. [20190522]DISABLE TABLE LOCK.txt

    [20190522]DISABLE TABLE LOCK.txt --//如果禁止table lock时,一些ddl操作会被禁止.但是我有点吃惊的是增加字段不受限制.--//通过测试说明问题. 1.环 ...

  8. 14.Java基础_函数/函数重载/参数传递

    Java函数和函数重载 /* 函数定义: public static 返回类型 func(参数){ 方法体: } 函数重载 在调用时,Java虚拟机会通过参数的不同来区分同名的函数 满足: 1.多个函 ...

  9. 谈谈你对OOM的理解?

    (1)整体架构 (1)ByteBuffer使用native方法,直接在堆外分配内存. 当堆外内存(也即本地物理内存)不够时,就会抛出这个异常     ----GC Direct buffer memo ...

  10. luoguP3531 [POI2012]LIT-Letters

    (https://www.luogu.org/problem/P3531) 注意编号 #include<cstdio> #include<algorithm> #include ...