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手勢的移動,旋轉和縮放,也加入了各種觸摸事件來處理多個點的觸摸,通過這些事件可以獲取到多點觸摸的坐標,從而實現各種多點邏輯。是否覺得很強大?