WPF进阶技巧和实战09-事件(2-多点触控)
多点触控输入
多点触控输入和传统的基于比的输入的区别是多点触控识别手势,用户可以移动多根手指以执行常见的操作,放大,旋转,拖动等。
多点触控的输入层次
WPF允许使用键盘和鼠标的高层次输入(例如单击和文本改变)和低层次输入(鼠标事件和按键事件)。多点触控输入同样应用了这种多层次的输入方式,WPF提供了3个独立的层次:
- 原始触控(raw touch):这是最低级的支持,可访问用户执行的每个触控。缺点是由应用程序负责将单独的触控消息组合在一起,并对他们进行解释。如果不准备识别标准触摸手势,反而希望创建以独特方式响应多点触控输入的应用程序,使用原始触控是合理的。一个例子就是绘图程序,允许用户同时使用多根手指在触摸屏上绘图。
- 操作(manipulation):这是一个简便的抽象层,该层将原始的多点触控输入转换成更有意义的手势,与WPF控件将一系列MouseDown和MouseUp事件解释为更高级的MouseDoubleClick事件相似。WPF支持的通用手势包括移动Pan,缩放Zoom,旋转Rotate,轻按Tap
- 内置的元素支持:有些元素已经对多点触控事件提供了内置的支持,从而不需要在编写代码。例如,可滚动的控件支持触控移动,ListBox、ListView、DataGrid、TextBox、ScrollViewer
原始触控
触控事件被内置到了低级的UIElement以及ContentElemnet类。所有元素的原始触控事件:
| 名称 | 路由类型 | 说明 |
|---|---|---|
| PreviewTouchDown | 隧道 | 当用户触摸元素时发生 |
| TouchDown | 冒泡 | 当用户触摸元素时发生 |
| PreviewTouchMove | 隧道 | 当用户移动放到触摸屏上的手指时发生 |
| TouchMove | 冒泡 | 当用户移动放到触摸屏上的手指时发生 |
| PreviewTouchUp | 隧道 | 当用户移开手指,结束触摸时发生 |
| TouchUp | 冒泡 | 当用户移开手指,结束触摸时发生 |
| TouchEnter | 无 | 当触点从元素外进入元素内时发生 |
| TouchLeave | 无 | 当触点离开元素时发生 |
所有这些事件都提供了一个TouchEventArgs对象,该对象提供了两个重要成员。第一个是GetTouchPoint()方法,该方法返回触控事件发生位置的屏幕坐标(还有触点的大小等)。第二个是TouchDevice属性,该属性返回一个TouchDevice对象。这里的技巧是将每个触点视为单独设备。因此,如果用户在不同的位置按下两根手指(同时按下或者先按下一个再按下一个),WPF将他们作为两个触控设备,并为每个触控设备指定唯一的ID,当用户移动这些手指,并且触控事件发生时,代码可以通过TouchDevice.ID属性区分两个触点。
操作
WPF为手势提供了更高级的支持,称为触控操作。通过将元素的IsManipulationEnabled属性设置为true,使元素接受触控操作。然后可响应4个操作事件:
ManipulationStarting、ManipulationStarted、ManipulationDelta、ManipulationComplted。
<Window x:Class="Multitouch.Manipulations"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Manipulations" Height="349" Width="607">
<Grid>
<Canvas x:Name="canvas" ManipulationStarting="image_ManipulationStarting" ManipulationDelta="image_ManipulationDelta">
<Image Canvas.Top="10" Canvas.Left="10" Width="200" IsManipulationEnabled="True" Source="koala.jpg">
<Image.RenderTransform>
<MatrixTransform></MatrixTransform>
</Image.RenderTransform>
</Image>
<Image Canvas.Top="30" Canvas.Left="350" Width="200" IsManipulationEnabled="True" Source="penguins.jpg">
<Image.RenderTransform>
<MatrixTransform></MatrixTransform>
</Image.RenderTransform>
</Image>
<Image Canvas.Top="100" Canvas.Left="200" Width="200" IsManipulationEnabled="True" Source="tulips.jpg">
<Image.RenderTransform>
<MatrixTransform></MatrixTransform>
</Image.RenderTransform>
</Image>
</Canvas>
</Grid>
</Window>
public partial class Manipulations : Window
{
public Manipulations()
{
InitializeComponent();
}
private void image_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
// Set the container (used for coordinates.)
e.ManipulationContainer = canvas;
// Choose what manipulations to allow.
e.Mode = ManipulationModes.All;
}
private void image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
// Get the image that's being manipulated.
FrameworkElement element = (FrameworkElement)e.Source;
// Use the matrix to manipulate the element.
Matrix matrix = ((MatrixTransform)element.RenderTransform).Matrix;
var deltaManipulation = e.DeltaManipulation;
// Find the old center, and apply the old manipulations.
Point center = new Point(element.ActualWidth / 2, element.ActualHeight / 2);
center = matrix.Transform(center);
// Apply zoom manipulations.
matrix.ScaleAt(deltaManipulation.Scale.X, deltaManipulation.Scale.Y, center.X, center.Y);
// Apply rotation manipulations.
matrix.RotateAt(e.DeltaManipulation.Rotation, center.X, center.Y);
// Apply panning.
matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);
// Set the final matrix.
((MatrixTransform)element.RenderTransform).Matrix = matrix;
}
}
上面每个图像都包含一个MatrixTransform对象,该对象为代码应用移动、旋转、缩放等操作的组合提供了一个简易方式。当操作发生时,将使用代码改变他们。
当触摸一幅图时,将触发ManipulationStarting事件。这时,设置操作容器(后面将获得所有操作坐标的参考点)。当操作发生时,触发ManipulationDelta事件,例如用户开始旋转一幅图像,将不断触发这个事件,直到用户旋转停止或者抬起手指为止。
通过使用ManipulationDelta对象将手势的当前状态记录下来,该对象是通过ManipulationDeltaEventArgs.DeltaManipulation属性提供的。本质上,ManipulationDelta对象记录了应该应用到对象的缩放、旋转、移动的量,分别有3个简单的属性提供,Scale、Rotation、Translation,通过这3个数据来调整用户界面的元素。
惯性
本质上,通过惯性可以更逼真的更流畅的操作元素。如上例中,当手指从触摸屏抬起时图像会立即停止一定。但如果启用了惯性特性,那么图像会继续移动非常短的一段时间,正常地减速。将元素拖动进他们不能穿过的边界时,惯性还会使元素弹回来。
添加惯性特性,只需处理ManipulationInertiaStarting事件。该事件从一幅图像开始并冒泡到Canvas面板。当用户结束手势并抬起手指释放元素时,触发该事件。可使用ManipulationInertiaStartingEventArgs对象确定当前速度,并设置希望的减速度。
WPF进阶技巧和实战09-事件(2-多点触控)的更多相关文章
- WPF进阶技巧和实战03-控件(3-文本控件及列表控件)
系列文章链接 WPF进阶技巧和实战01-小技巧 WPF进阶技巧和实战02-布局 WPF进阶技巧和实战03-控件(1-控件及内容控件) WPF进阶技巧和实战03-控件(2-特殊容器) WPF进阶技巧和实 ...
- WPF进阶技巧和实战03-控件(4-基于范围的控件及日期控件)
系列文章链接 WPF进阶技巧和实战01-小技巧 WPF进阶技巧和实战02-布局 WPF进阶技巧和实战03-控件(1-控件及内容控件) WPF进阶技巧和实战03-控件(2-特殊容器) WPF进阶技巧和实 ...
- WPF进阶技巧和实战09-事件(1-路由事件、鼠标键盘输入)
理解路由事件 当有意义的事情发生时,有对象(WPF的元素)发送的用于通知代码的消息,就是事件的核心思想.WPF通过事件路由的概念增强了.NET事件模型.事件由允许源自某个元素的事件由另一个元素引发.例 ...
- WPF进阶技巧和实战08-依赖属性与绑定01
依赖项属性 定义依赖项属性 注意:只能为依赖对象(继承自DependencyObject的类)添加依赖项属性.WPF中的元素基本上都继承自DependencyObject类. 静态字段 名称约定(属性 ...
- WPF进阶技巧和实战07--自定义元素01
完善和扩展标准控件的方法: 样式:可使用样式方便地重用控件属性的集合,甚至可以使用触发器应用效果 内容控件:所有继承自ContentControl类的控件都支持嵌套的内容.使用内容控件,可以快速创建聚 ...
- WPF进阶技巧和实战03-控件(5-列表、树、网格02)
数据模板 样式提供了基本的格式化能力,但是不管如何修改ListBoxItem,他都不能够展示功能更强大的元素组合,因为了每个ListBoxItem只支持单个绑定字段(通过DisplayMemberPa ...
- WPF进阶技巧和实战03-控件(1-控件及内容控件)
所有控件都继承自System.Windows.Controls.Control类,这个类添加一些基本结构: 设置控件内容对齐方式 (HorizontalContentAlignment,Vertica ...
- WPF进阶技巧和实战08-依赖属性与绑定02
将元素绑定在一起 数据绑定最简单的形式是:源对象是WPF元素而且源属性是依赖项属性.依赖项属性内置了更改通知支持,当源对象中改变依赖项属性时,会立即更新目标对象的绑定属性. 元素绑定到元素也是经常使用 ...
- WPF进阶技巧和实战08-依赖属性与绑定03
数据提供者 在大多数的代码中,都是通过设置元素的DataContext属性或者列表控件的ItemsSource属性,从而提供顶级的数据源.当数据对象是通过另一个类构造时,可以有其他选择. 一种是作为窗 ...
随机推荐
- 鸿蒙内核源码分析(信号量篇) | 谁在负责解决任务的同步 | 百篇博客分析OpenHarmony源码 | v29.01
百篇博客系列篇.本篇为: v29.xx 鸿蒙内核源码分析(信号量篇) | 谁在负责解决任务的同步 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁当立 ...
- mysql从零开始之MySQL 选择数据库
MySQL 选择数据库 在你连接到 MySQL 数据库后,可能有多个可以操作的数据库,所以你需要选择你要操作的数据库. 从命令提示窗口中选择MySQL数据库 在 mysql> 提示窗口中可以很简 ...
- 树莓派3B搭建NODE-RED运行环境并构建数据流
树莓派3B搭建NODE-RED运行环境并构建数据流 树莓派搭建Node-RED环境 树莓派自2015年开始是默认就带NODE-RED的,但是如今已是2018年:)自带的版本已经很老了,可通过下面的命令 ...
- 如何评估 Serverless 服务能力?这份报告给出了 40 条标准
编者按:两年前,我们还在讨论什么是 Serverless,Serverless 如何落地.如今,已经有评测机构给出了 40 条标准来对 Serverless 的服务能力进行评估,这些评估细则既是技术生 ...
- 小白自制Linux开发板 番外篇 一 modprobe加载驱动问题(转载整理)
使用modprobe加载驱动 转载地址:https://blog.csdn.net/qq_39101111/article/details/78773362 前面我们提到,modprobe并不需要指定 ...
- 无法获取指向控制台的文件描述符 (couldn't get a file descriptor referring to the console)
背景 最近收拾东西,从一堆杂物里翻出来尘封四年多的树莓派 3B 主机来,打扫打扫灰尘,接上电源,居然还能通过之前设置好的 VNC 连上.欣慰之余,开始 clone 我的 git 项目,为它们拓展一个新 ...
- NX 图标
vector_on_curve crosscut_zig_zag_with_lifts vector_along_curve zlevel_zig add_new_sc zlevel_zi ...
- 痞子衡嵌入式:超级下载算法RT-UFL v1.0在恩智浦MCUXpresso IDE下的使用
痞子衡主导的"学术"项目 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计> v1.0 版发布近 4 个月了,部分客户已经在实际项目开发调试中用上了这个 ...
- Go语言核心36讲(Go语言进阶技术四)--学习笔记
10 | 通道的基本操作 作为 Go 语言最有特色的数据类型,通道(channel)完全可以与 goroutine(也可称为 go 程)并驾齐驱,共同代表 Go 语言独有的并发编程模式和编程哲学. D ...
- programmercarl——数组——二分查找
二分查找,在经过: 34--https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-arr ...