WPF中的多点触摸事件
UIElement在WPF4下添加了很多支持多点触摸的事件,通过它们可以在硬件支持的情况下处理多点触摸,以下通过代码来说明通过处理这些事件,我们可以做些什么:
一.触摸相关的多种事件,跟鼠标事件是对应的,通过这些事件可以获取到多个触摸的鼠标点,并进行相应的处理
public static readonly RoutedEvent TouchDownEvent; public static readonly RoutedEvent TouchEnterEvent; public static readonly RoutedEvent TouchLeaveEvent; public static readonly RoutedEvent TouchMoveEvent; public static readonly RoutedEvent TouchUpEvent;
以上每个事件都包含一个TouchEventArgs参数,通过该参数可以获取到一个TouchDevice信息,对应于每一次触摸,还可以通过GetTouchPoint得到一个TouchPoint,TouchPoint包含当前触摸的动作,触摸的位置等信息,通过获取到的TouchDevice,我们可以处理每一次触摸(通过判断TouchDevice的ID号来分辨不同的触摸),并通过TouchPoint获取触摸的坐标点,从而实现一些多点的逻辑,例如多点的书写(通过获取的TouchPoint来生成PathFigure,形成PathGeometry,最终填充成Path来绘制)
二.Manipulation事件,通过这些事件可以实现UIElement的一些多点手势(移动,旋转,缩放)
public static readonly RoutedEvent ManipulationCompletedEven; public static readonly RoutedEvent ManipulationDeltaEvent; public static readonly RoutedEvent ManipulationInertiaStartingEvent; public static readonly RoutedEvent ManipulationStartedEvent;
1.要处理Manipulation事件,首先必须设置UIElement的IsManipulationEnabled为true
2.ManipulationInertiaStartingEvent事件包含一个ManipulationStartingEventArgs参数,通过该参数可以设置:
UIElement的ManipulationContainer —— 设置该UIElement的容器
Mode —— 处理的事件类型,包含以下枚举
None:不处理
TranslateX:处理水平移动
TranslateY:处理垂直移动
Translate:处理移动
Rotate:处理旋转
Scale:处理缩放
All:处理所有事件
3.要实现控件的移动,缩放,旋转,可以在控件的ManipulationDeltaEvent事件中使用以下代码:
private void image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) { var element = e.Source as FrameworkElement; if (element != null) { try { ManipulationDelta deltaManipulation = e.DeltaManipulation; Matrix matrix = element.RenderTransform.Value; Point center = new Point(element.ActualWidth / 2, element.ActualHeight / 2); center = matrix.Transform(center); //设置中心点 //处理缩放 matrix.ScaleAt(deltaManipulation.Scale.X, deltaManipulation.Scale.Y, center.X, center.Y); // 处理旋转 matrix.RotateAt(e.DeltaManipulation.Rotation, center.X, center.Y); //处理移动 matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y); element.RenderTransform = new MatrixTransform(matrix); e.Handled = true; } catch (Exception ei) { MessageBox.Show(ei.ToString()); } } }
4.此外可以在ManipulationInertiaStarting事件中设置惯性效果
private void image_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e) { // 移动惯性 e.TranslationBehavior = new InertiaTranslationBehavior() { InitialVelocity = e.InitialVelocities.LinearVelocity, DesiredDeceleration = 1 / (1000.0 * 1000.0) // 单位:一个WPF单位 / ms }; // 缩放惯性 e.ExpansionBehavior = new InertiaExpansionBehavior() { InitialVelocity = e.InitialVelocities.ExpansionVelocity, DesiredDeceleration = 1 / 1000.0 * 1000.0 // 单位:一个WPF单位 / ms }; // 旋转惯性 e.RotationBehavior = new InertiaRotationBehavior() { InitialVelocity = e.InitialVelocities.AngularVelocity, DesiredDeceleration = 720 / (1000.0 * 1000.0) //单位:一个角度 / ms }; e.Handled = true; }
5.在设置了惯性事件后,如果不处理判断控件容器的边界,那很容易一个移动就会把控件移到屏幕外部,因此此时可以在ManipulationDeltaEvent事件中加入以下代码:
if (e.IsInertial) { Rect containingRect = new Rect(((FrameworkElement)e.ManipulationContainer).RenderSize); Rect shapeBounds = element.RenderTransform.TransformBounds(new Rect(element.RenderSize)); if (e.IsInertial && !containingRect.Contains(shapeBounds)) { e.ReportBoundaryFeedback(e.DeltaManipulation); e.Complete(); } }
三.总结
WPF4直接加入了Manipulation事件来支持对UIElement手势的移动,旋转和缩放,也加入了各种触摸事件来处理多个点的触摸,通过这些事件可以获取到多点触摸的坐标,从而实现各种多点逻辑。是否觉得很强大?