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