diff --git a/Samples/Input/cs-winui/DeviceCapabilities.xaml b/Samples/Input/cs-winui/DeviceCapabilities.xaml
new file mode 100644
index 000000000..497ad43d8
--- /dev/null
+++ b/Samples/Input/cs-winui/DeviceCapabilities.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+ This scenario demonstrates how to use the KeyboardCapabilities, MouseCapabilities, and TouchCapabilities classes to determine what type of input the current device an app is running on supports.
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/Input/cs-winui/DeviceCapabilities.xaml.cs b/Samples/Input/cs-winui/DeviceCapabilities.xaml.cs
new file mode 100644
index 000000000..2591d646f
--- /dev/null
+++ b/Samples/Input/cs-winui/DeviceCapabilities.xaml.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Text;
+using Microsoft.UI.Xaml.Controls;
+using Windows.Devices.Input;
+
+namespace Input
+{
+ public sealed partial class DeviceCapabilities : Page
+ {
+ public DeviceCapabilities()
+ {
+ this.InitializeComponent();
+
+ KeyboardCapabilities kbdCapabilities = new KeyboardCapabilities();
+ keyboardText.Text = "Keyboard present = " + kbdCapabilities.KeyboardPresent.ToString();
+
+ MouseCapabilities mouseCapabilities = new MouseCapabilities();
+ StringBuilder sb = new StringBuilder();
+ sb.Append("Mouse present = " + mouseCapabilities.MousePresent.ToString() + "\n");
+ sb.Append("Number of buttons = " + mouseCapabilities.NumberOfButtons.ToString() + "\n");
+ sb.Append("Vertical wheel present = " + mouseCapabilities.VerticalWheelPresent.ToString() + "\n");
+ sb.Append("Horizontal wheel present = " + mouseCapabilities.HorizontalWheelPresent.ToString() + "\n");
+ sb.Append("Buttons swapped = " + mouseCapabilities.SwapButtons.ToString());
+ mouseText.Text = sb.ToString();
+
+ TouchCapabilities touchCapabilities = new TouchCapabilities();
+ sb = new StringBuilder();
+ sb.Append("Touch present = " + touchCapabilities.TouchPresent.ToString() + "\n");
+ sb.Append("Touch contacts supported = " + touchCapabilities.Contacts.ToString());
+ touchText.Text = sb.ToString();
+ }
+ }
+}
diff --git a/Samples/Input/cs-winui/Input.csproj b/Samples/Input/cs-winui/Input.csproj
index febae7985..21d5a2630 100644
--- a/Samples/Input/cs-winui/Input.csproj
+++ b/Samples/Input/cs-winui/Input.csproj
@@ -12,9 +12,14 @@
Properties\PublishProfiles\win10-$(Platform).pubxml
+
+
+
+
+
@@ -30,6 +35,7 @@
+
@@ -41,6 +47,11 @@
+
+
+ MSBuild:Compile
+
+
MSBuild:Compile
@@ -56,4 +67,24 @@
MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+
+
+ MSBuild:Compile
+
+
+
+
+ MSBuild:Compile
+
+
+
+
+ MSBuild:Compile
+
+
diff --git a/Samples/Input/cs-winui/PointerEllipse.xaml b/Samples/Input/cs-winui/PointerEllipse.xaml
new file mode 100644
index 000000000..1b1585ddd
--- /dev/null
+++ b/Samples/Input/cs-winui/PointerEllipse.xaml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/Input/cs-winui/PointerEllipse.xaml.cs b/Samples/Input/cs-winui/PointerEllipse.xaml.cs
new file mode 100644
index 000000000..916210e82
--- /dev/null
+++ b/Samples/Input/cs-winui/PointerEllipse.xaml.cs
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Media;
+
+namespace Input
+{
+ public sealed partial class PointerEllipse : UserControl
+ {
+ private bool primaryEllipse;
+
+ public PointerEllipse()
+ {
+ this.InitializeComponent();
+ ApplyPointerStyle(false);
+ }
+
+ public uint PointerId { get; set; }
+
+ public bool PrimaryPointer { get; set; }
+
+ public bool PrimaryEllipse
+ {
+ get => primaryEllipse;
+ set
+ {
+ primaryEllipse = value;
+ ApplyPointerStyle(value);
+ }
+ }
+
+ public double Diameter => 120.0;
+
+ private void ApplyPointerStyle(bool isPrimary)
+ {
+ if (isPrimary)
+ {
+ ellipse.Fill = new SolidColorBrush(Colors.White);
+ ellipse.Stroke = new SolidColorBrush(Colors.Red);
+ PrimaryPointerStoryboard.Begin();
+ }
+ else
+ {
+ PrimaryPointerStoryboard.Stop();
+ ellipse.Fill = new SolidColorBrush(Colors.LightSkyBlue);
+ ellipse.Stroke = new SolidColorBrush(Colors.DodgerBlue);
+ }
+ }
+ }
+}
diff --git a/Samples/Input/cs-winui/PointerPointProperties.xaml b/Samples/Input/cs-winui/PointerPointProperties.xaml
new file mode 100644
index 000000000..5175f5afb
--- /dev/null
+++ b/Samples/Input/cs-winui/PointerPointProperties.xaml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The PointerPoint class provides basic properties for the input pointer associated with a single mouse, pen/stylus, or touch contact. This scenario demonstrates how to retrieve a PointerPoint object in response to an input event, determine what type of input it is (mouse, pen, or touch), and retrieve properties present for all input types and those specific to its type.
+
+
+
+
+
+
+
diff --git a/Samples/Input/cs-winui/PointerPointProperties.xaml.cs b/Samples/Input/cs-winui/PointerPointProperties.xaml.cs
new file mode 100644
index 000000000..5d7b9e001
--- /dev/null
+++ b/Samples/Input/cs-winui/PointerPointProperties.xaml.cs
@@ -0,0 +1,194 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.UI;
+using Microsoft.UI.Input;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Media;
+using WinUIPointerPointProperties = Microsoft.UI.Input.PointerPointProperties;
+
+namespace Input
+{
+ public sealed partial class PointerPointProperties : Page
+ {
+ private readonly Dictionary popups;
+
+ public PointerPointProperties()
+ {
+ this.InitializeComponent();
+
+ popups = new Dictionary();
+
+ mainCanvas.PointerPressed += new PointerEventHandler(Pointer_Pressed);
+ mainCanvas.PointerMoved += new PointerEventHandler(Pointer_Moved);
+ mainCanvas.PointerReleased += new PointerEventHandler(Pointer_Released);
+ mainCanvas.PointerExited += new PointerEventHandler(Pointer_Released);
+ mainCanvas.PointerEntered += new PointerEventHandler(Pointer_Entered);
+ mainCanvas.PointerWheelChanged += new PointerEventHandler(Pointer_Wheel_Changed);
+ }
+
+ private void Pointer_Pressed(object sender, PointerRoutedEventArgs e)
+ {
+ PointerPoint currentPoint = e.GetCurrentPoint(mainCanvas);
+ CreateOrUpdatePropertyPopUp(currentPoint);
+ }
+
+ private void Pointer_Entered(object sender, PointerRoutedEventArgs e)
+ {
+ PointerPoint currentPoint = e.GetCurrentPoint(mainCanvas);
+ if (currentPoint.IsInContact)
+ {
+ CreateOrUpdatePropertyPopUp(currentPoint);
+ }
+ }
+
+ private void Pointer_Moved(object sender, PointerRoutedEventArgs e)
+ {
+ PointerPoint currentPoint = e.GetCurrentPoint(mainCanvas);
+ if (currentPoint.IsInContact)
+ {
+ CreateOrUpdatePropertyPopUp(currentPoint);
+ }
+ }
+
+ private void Pointer_Released(object sender, PointerRoutedEventArgs e)
+ {
+ PointerPoint currentPoint = e.GetCurrentPoint(mainCanvas);
+ HidePropertyPopUp(currentPoint);
+ }
+
+ private void Pointer_Wheel_Changed(object sender, PointerRoutedEventArgs e)
+ {
+ PointerPoint currentPoint = e.GetCurrentPoint(mainCanvas);
+ if (currentPoint.IsInContact)
+ {
+ CreateOrUpdatePropertyPopUp(currentPoint);
+ }
+ }
+
+ private void CreateOrUpdatePropertyPopUp(PointerPoint currentPoint)
+ {
+ string pointerProperties = GetPointerProperties(currentPoint);
+ string deviceSpecificProperties = GetDeviceSpecificProperties(currentPoint);
+ RenderPropertyPopUp(pointerProperties, deviceSpecificProperties, currentPoint);
+ }
+
+ private static string GetPointerProperties(PointerPoint currentPoint)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("ID: " + currentPoint.PointerId);
+ sb.Append("\nX: " + currentPoint.Position.X);
+ sb.Append("\nY: " + currentPoint.Position.Y);
+ sb.Append("\nContact: " + currentPoint.IsInContact + "\n");
+ return sb.ToString();
+ }
+
+ private static string GetDeviceSpecificProperties(PointerPoint currentPoint)
+ {
+ string deviceSpecificProperties = string.Empty;
+ switch (currentPoint.PointerDeviceType)
+ {
+ case PointerDeviceType.Mouse:
+ deviceSpecificProperties = GetMouseProperties(currentPoint);
+ break;
+ case PointerDeviceType.Pen:
+ deviceSpecificProperties = GetPenProperties(currentPoint);
+ break;
+ case PointerDeviceType.Touch:
+ deviceSpecificProperties = GetTouchProperties(currentPoint);
+ break;
+ }
+
+ return deviceSpecificProperties;
+ }
+
+ private static string GetMouseProperties(PointerPoint currentPoint)
+ {
+ WinUIPointerPointProperties pointerProperties = currentPoint.Properties;
+ StringBuilder sb = new StringBuilder();
+ sb.Append("Left button: " + pointerProperties.IsLeftButtonPressed);
+ sb.Append("\nRight button: " + pointerProperties.IsRightButtonPressed);
+ sb.Append("\nMiddle button: " + pointerProperties.IsMiddleButtonPressed);
+ sb.Append("\nX1 button: " + pointerProperties.IsXButton1Pressed);
+ sb.Append("\nX2 button: " + pointerProperties.IsXButton2Pressed);
+ sb.Append("\nMouse wheel delta: " + pointerProperties.MouseWheelDelta);
+ return sb.ToString();
+ }
+
+ private static string GetTouchProperties(PointerPoint currentPoint)
+ {
+ WinUIPointerPointProperties pointerProperties = currentPoint.Properties;
+ StringBuilder sb = new StringBuilder();
+ sb.Append("Contact Rect X: " + pointerProperties.ContactRect.X);
+ sb.Append("\nContact Rect Y: " + pointerProperties.ContactRect.Y);
+ sb.Append("\nContact Rect Width: " + pointerProperties.ContactRect.Width);
+ sb.Append("\nContact Rect Height: " + pointerProperties.ContactRect.Height);
+ return sb.ToString();
+ }
+
+ private static string GetPenProperties(PointerPoint currentPoint)
+ {
+ WinUIPointerPointProperties pointerProperties = currentPoint.Properties;
+ StringBuilder sb = new StringBuilder();
+ sb.Append("Barrel button: " + pointerProperties.IsBarrelButtonPressed);
+ sb.Append("\nEraser: " + pointerProperties.IsEraser);
+ sb.Append("\nPressure: " + pointerProperties.Pressure);
+ return sb.ToString();
+ }
+
+ private void RenderPropertyPopUp(string pointerProperties, string deviceSpecificProperties, PointerPoint currentPoint)
+ {
+ if (popups.ContainsKey(currentPoint.PointerId))
+ {
+ TextBlock pointerText = (TextBlock)popups[currentPoint.PointerId].Children[0];
+ pointerText.Text = pointerProperties;
+ TextBlock deviceSpecificText = (TextBlock)popups[currentPoint.PointerId].Children[1];
+ deviceSpecificText.Text = deviceSpecificProperties;
+ }
+ else
+ {
+ StackPanel pointerPanel = new StackPanel();
+ TextBlock pointerText = new TextBlock();
+ pointerText.Text = pointerProperties;
+ pointerPanel.Children.Add(pointerText);
+
+ TextBlock deviceSpecificText = new TextBlock();
+ deviceSpecificText.Text = deviceSpecificProperties;
+
+ switch (currentPoint.PointerDeviceType)
+ {
+ case PointerDeviceType.Mouse:
+ deviceSpecificText.Foreground = new SolidColorBrush(Colors.Red);
+ break;
+ case PointerDeviceType.Touch:
+ deviceSpecificText.Foreground = new SolidColorBrush(Colors.Green);
+ break;
+ case PointerDeviceType.Pen:
+ deviceSpecificText.Foreground = new SolidColorBrush(Colors.Yellow);
+ break;
+ }
+
+ pointerPanel.Children.Add(deviceSpecificText);
+ popups[currentPoint.PointerId] = pointerPanel;
+ mainCanvas.Children.Add(popups[currentPoint.PointerId]);
+ }
+
+ TranslateTransform transform = new TranslateTransform();
+ transform.X = currentPoint.Position.X + 24;
+ transform.Y = currentPoint.Position.Y + 24;
+ popups[currentPoint.PointerId].RenderTransform = transform;
+ }
+
+ private void HidePropertyPopUp(PointerPoint currentPoint)
+ {
+ if (popups.ContainsKey(currentPoint.PointerId))
+ {
+ mainCanvas.Children.Remove(popups[currentPoint.PointerId]);
+ popups.Remove(currentPoint.PointerId);
+ }
+ }
+ }
+}
diff --git a/Samples/Input/cs-winui/PointerTracking.xaml b/Samples/Input/cs-winui/PointerTracking.xaml
new file mode 100644
index 000000000..a71b81d7f
--- /dev/null
+++ b/Samples/Input/cs-winui/PointerTracking.xaml
@@ -0,0 +1,49 @@
+
+
+
+
+
+ Demonstrates multi-pointer tracking with pointer entered, pressed, moved, released, exited, canceled, and capture lost events.
+ The primary pointer is highlighted with an animated ellipse while secondary pointers use static feedback.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/Input/cs-winui/PointerTracking.xaml.cs b/Samples/Input/cs-winui/PointerTracking.xaml.cs
new file mode 100644
index 000000000..139d3e558
--- /dev/null
+++ b/Samples/Input/cs-winui/PointerTracking.xaml.cs
@@ -0,0 +1,152 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI.Input;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Input;
+using System.Collections.Generic;
+using Windows.Foundation;
+
+namespace Input
+{
+ public sealed partial class PointerTracking : Page
+ {
+ private readonly Dictionary ellipses = new Dictionary();
+ private bool primaryExists;
+
+ public PointerTracking()
+ {
+ this.InitializeComponent();
+ }
+
+ private void OnPointerEntered(object sender, PointerRoutedEventArgs e)
+ {
+ if (!e.Pointer.IsInContact)
+ {
+ AddPointer(e, "Entered");
+ }
+
+ e.Handled = true;
+ }
+
+ private void OnPointerPressed(object sender, PointerRoutedEventArgs e)
+ {
+ pointerCanvas.CapturePointer(e.Pointer);
+ AddPointer(e, "Pressed");
+ e.Handled = true;
+ }
+
+ private void OnPointerMoved(object sender, PointerRoutedEventArgs e)
+ {
+ PointerPoint pointerPoint = e.GetCurrentPoint(pointerCanvas);
+ if (ellipses.TryGetValue(pointerPoint.PointerId, out PointerEllipse ellipse))
+ {
+ UpdateEllipsePosition(ellipse, pointerPoint.Position);
+ UpdateLastEvent("Moved", pointerPoint.PointerId);
+ }
+
+ e.Handled = true;
+ }
+
+ private void OnPointerReleased(object sender, PointerRoutedEventArgs e)
+ {
+ RemovePointer(e, "Released", true);
+ e.Handled = true;
+ }
+
+ private void OnPointerExited(object sender, PointerRoutedEventArgs e)
+ {
+ if (!e.Pointer.IsInContact)
+ {
+ RemovePointer(e, "Exited", true);
+ }
+
+ e.Handled = true;
+ }
+
+ private void OnPointerCanceled(object sender, PointerRoutedEventArgs e)
+ {
+ RemovePointer(e, "Canceled", true);
+ e.Handled = true;
+ }
+
+ private void OnPointerCaptureLost(object sender, PointerRoutedEventArgs e)
+ {
+ RemovePointer(e, "CaptureLost", false);
+ e.Handled = true;
+ }
+
+ private void AddPointer(PointerRoutedEventArgs e, string eventName)
+ {
+ PointerPoint pointerPoint = e.GetCurrentPoint(pointerCanvas);
+ if (ellipses.TryGetValue(pointerPoint.PointerId, out PointerEllipse existingEllipse))
+ {
+ UpdateEllipsePosition(existingEllipse, pointerPoint.Position);
+ UpdateLastEvent(eventName, pointerPoint.PointerId);
+ return;
+ }
+
+ PointerEllipse pointerEllipse = new PointerEllipse();
+ pointerEllipse.PointerId = pointerPoint.PointerId;
+
+ if (pointerPoint.Properties.IsPrimary && !primaryExists)
+ {
+ pointerEllipse.PrimaryPointer = true;
+ pointerEllipse.PrimaryEllipse = true;
+ primaryExists = true;
+ PointerPrimary.Text = pointerPoint.PointerId.ToString();
+ }
+ else
+ {
+ pointerEllipse.PrimaryPointer = false;
+ pointerEllipse.PrimaryEllipse = false;
+ }
+
+ ellipses[pointerPoint.PointerId] = pointerEllipse;
+ UpdateEllipsePosition(pointerEllipse, pointerPoint.Position);
+ pointerCanvas.Children.Add(pointerEllipse);
+ UpdatePointerCount();
+ UpdateLastEvent(eventName, pointerPoint.PointerId);
+ }
+
+ private void RemovePointer(PointerRoutedEventArgs e, string eventName, bool releaseCapture)
+ {
+ if (releaseCapture)
+ {
+ pointerCanvas.ReleasePointerCapture(e.Pointer);
+ }
+
+ PointerPoint pointerPoint = e.GetCurrentPoint(pointerCanvas);
+ if (pointerPoint.Properties.IsPrimary)
+ {
+ PointerPrimary.Text = "n/a";
+ primaryExists = false;
+ }
+
+ if (ellipses.TryGetValue(pointerPoint.PointerId, out PointerEllipse ellipse))
+ {
+ pointerCanvas.Children.Remove(ellipse);
+ ellipses.Remove(pointerPoint.PointerId);
+ UpdatePointerCount();
+ }
+
+ UpdateLastEvent(eventName, pointerPoint.PointerId);
+ }
+
+ private void UpdateEllipsePosition(PointerEllipse ellipse, Point position)
+ {
+ Canvas.SetLeft(ellipse, position.X - (ellipse.Diameter / 2.0));
+ Canvas.SetTop(ellipse, position.Y - (ellipse.Diameter / 2.0));
+ }
+
+ private void UpdatePointerCount()
+ {
+ PointerCounter.Text = ellipses.Count.ToString();
+ }
+
+ private void UpdateLastEvent(string eventName, uint pointerId)
+ {
+ LastEvent.Text = eventName + " (" + pointerId.ToString() + ")";
+ }
+ }
+}
diff --git a/Samples/Input/cs-winui/Properties/launchSettings.json b/Samples/Input/cs-winui/Properties/launchSettings.json
index 0a4d92d93..52545798a 100644
--- a/Samples/Input/cs-winui/Properties/launchSettings.json
+++ b/Samples/Input/cs-winui/Properties/launchSettings.json
@@ -1,10 +1,10 @@
-{
+{
"profiles": {
- "Input (Package)": {
- "commandName": "MsixPackage"
- },
"Input (Unpackaged)": {
"commandName": "Project"
+ },
+ "Input (Package)": {
+ "commandName": "MsixPackage"
}
}
}
\ No newline at end of file
diff --git a/Samples/Input/cs-winui/SampleConfiguration.cs b/Samples/Input/cs-winui/SampleConfiguration.cs
index 903541f91..5f0ab16b0 100644
--- a/Samples/Input/cs-winui/SampleConfiguration.cs
+++ b/Samples/Input/cs-winui/SampleConfiguration.cs
@@ -19,7 +19,11 @@ public partial class MainPage : Page
{
new Scenario() { Title = "Gesture Recognizer", ClassName = typeof(GestureRecognizer).FullName },
new Scenario() { Title = "Gesture Recognizer Manipulations", ClassName = typeof(GestureRecognizerManipulation).FullName },
- new Scenario() { Title = "Cursor", ClassName = typeof(InputCursor).FullName }
+ new Scenario() { Title = "Cursor", ClassName = typeof(InputCursor).FullName },
+ new Scenario() { Title = "PointerTracking", ClassName = typeof(PointerTracking).FullName },
+ new Scenario() { Title = "Pointer Point Properties", ClassName = typeof(PointerPointProperties).FullName },
+ new Scenario() { Title = "Device Capabilities", ClassName = typeof(DeviceCapabilities).FullName },
+ new Scenario() { Title = "XAML Manipulations", ClassName = typeof(XamlManipulations).FullName }
};
}
diff --git a/Samples/Input/cs-winui/XamlManipulations.xaml b/Samples/Input/cs-winui/XamlManipulations.xaml
new file mode 100644
index 000000000..88fd12cb6
--- /dev/null
+++ b/Samples/Input/cs-winui/XamlManipulations.xaml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This scenario demonstrates how to use the ManipulationMode property to register for specific manipulation events on XAML elements and how to listen for and react to these events, specifically the TranslateX, TranslateY, TranslateInertia, Rotate, and RotateInertia events. Through reacting to these events, the rectangle can be moved and rotated via direct user interaction.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/Input/cs-winui/XamlManipulations.xaml.cs b/Samples/Input/cs-winui/XamlManipulations.xaml.cs
new file mode 100644
index 000000000..fbd17a251
--- /dev/null
+++ b/Samples/Input/cs-winui/XamlManipulations.xaml.cs
@@ -0,0 +1,134 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.UI;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml.Media;
+using Windows.Foundation;
+
+namespace Input
+{
+ public sealed partial class XamlManipulations : Page
+ {
+ private TransformGroup transforms;
+ private MatrixTransform previousTransform;
+ private CompositeTransform deltaTransform;
+ private bool forceManipulationsToEnd;
+
+ public XamlManipulations()
+ {
+ this.InitializeComponent();
+ forceManipulationsToEnd = false;
+
+ InitOptions();
+ InitManipulationTransforms();
+
+ manipulateMe.ManipulationStarted += new ManipulationStartedEventHandler(ManipulateMe_ManipulationStarted);
+ manipulateMe.ManipulationDelta += new ManipulationDeltaEventHandler(ManipulateMe_ManipulationDelta);
+ manipulateMe.ManipulationCompleted += new ManipulationCompletedEventHandler(ManipulateMe_ManipulationCompleted);
+ manipulateMe.ManipulationInertiaStarting += new ManipulationInertiaStartingEventHandler(ManipulateMe_ManipulationInertiaStarting);
+
+ manipulateMe.ManipulationMode =
+ ManipulationModes.TranslateX |
+ ManipulationModes.TranslateY |
+ ManipulationModes.Rotate |
+ ManipulationModes.TranslateInertia |
+ ManipulationModes.RotateInertia;
+ }
+
+ private void InitManipulationTransforms()
+ {
+ transforms = new TransformGroup();
+ previousTransform = new MatrixTransform() { Matrix = Matrix.Identity };
+ deltaTransform = new CompositeTransform();
+
+ transforms.Children.Add(previousTransform);
+ transforms.Children.Add(deltaTransform);
+
+ manipulateMe.RenderTransform = transforms;
+ }
+
+ private void ManipulateMe_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
+ {
+ forceManipulationsToEnd = false;
+ manipulateMe.Background = new SolidColorBrush(Colors.DeepSkyBlue);
+ }
+
+ private void ManipulateMe_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
+ {
+ if (forceManipulationsToEnd)
+ {
+ e.Complete();
+ return;
+ }
+
+ previousTransform.Matrix = transforms.Value;
+
+ Point center = previousTransform.TransformPoint(new Point(e.Position.X, e.Position.Y));
+ deltaTransform.CenterX = center.X;
+ deltaTransform.CenterY = center.Y;
+
+ deltaTransform.Rotation = e.Delta.Rotation;
+ deltaTransform.TranslateX = e.Delta.Translation.X;
+ deltaTransform.TranslateY = e.Delta.Translation.Y;
+ }
+
+ private void ManipulateMe_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingRoutedEventArgs e)
+ {
+ manipulateMe.Background = new SolidColorBrush(Colors.RoyalBlue);
+ }
+
+ private void ManipulateMe_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
+ {
+ manipulateMe.Background = new SolidColorBrush(Colors.LightGray);
+ }
+
+ private void movementAxis_Changed(object sender, SelectionChangedEventArgs e)
+ {
+ manipulateMe.ManipulationMode |= ManipulationModes.TranslateX | ManipulationModes.TranslateY;
+
+ ComboBoxItem selectedItem = (ComboBoxItem)((ComboBox)sender).SelectedItem;
+ switch (selectedItem.Content.ToString())
+ {
+ case "X only":
+ manipulateMe.ManipulationMode ^= ManipulationModes.TranslateY;
+ break;
+ case "Y only":
+ manipulateMe.ManipulationMode ^= ManipulationModes.TranslateX;
+ break;
+ }
+ }
+
+ private void InertiaSwitch_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (manipulateMe != null)
+ {
+ if (inertiaSwitch.IsOn)
+ {
+ manipulateMe.ManipulationMode |= ManipulationModes.TranslateInertia | ManipulationModes.RotateInertia;
+ }
+ else
+ {
+ manipulateMe.ManipulationMode &= ~(ManipulationModes.TranslateInertia | ManipulationModes.RotateInertia);
+ }
+ }
+ }
+
+ private void InitOptions()
+ {
+ movementAxis.SelectedIndex = 0;
+ inertiaSwitch.IsOn = true;
+ }
+
+ private void resetButton_Pressed(object sender, RoutedEventArgs e)
+ {
+ forceManipulationsToEnd = true;
+ manipulateMe.RenderTransform = null;
+ movementAxis.SelectedIndex = 0;
+ InitOptions();
+ InitManipulationTransforms();
+ }
+ }
+}