Windows 7 is now available, it’s time to build new user experiences using the new stuff, like multi-touch!
To play with this new feature, I have started a Codeplex project at http://multitouch.codeplex.com containing a first WPF custom control (and some Silverlight 3 behaviors, check out the next posts for more info) to enable touch drag, zoom and rotation gestures using the .NET wrapper classes available on http://code.msdn.microsoft.com/WindowsTouch (see also my other post about the same topic).
The touch events are managed in the ApplyTemplate method:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (Windows7.Multitouch.TouchHandler. DigitizerCapabilities.IsMultiTouchReady)
{
//Find the Window containing the CustomControl
DependencyObject dpParent = this;
do { dpParent = LogicalTreeHelper.GetParent(dpParent); } while (dpParent.GetType().BaseType != typeof(Window));
//Enable Stylus events
if (dpParent != null) Factory.EnableStylusEvents(dpParent as Window);
//Get the touch Area
UIElement touchArea = (UIElement)GetTemplateChild("_touchArea");
//Handle Stylus events
if (touchArea != null)
{
this.StylusDown += (s, e) => { _processor.ProcessDown((uint)e.StylusDevice.Id, e.GetPosition(touchArea).ToDrawingPointF()); };
this.StylusUp += (s, e) => { _processor.ProcessUp((uint)e.StylusDevice.Id, e.GetPosition(touchArea).ToDrawingPointF()); };
this.StylusMove += (s, e) => { _processor.ProcessMove((uint)e.StylusDevice.Id, e.GetPosition(touchArea).ToDrawingPointF()); };
//Handle the ManipulationDelta and the gestures
this._processor.ManipulationDelta += ProcessManipulationDelta;
this._processor.PivotRadius = 2;
}
}
}
When the ManipulationDelta event occurs, the ProcessManipulationDelta handler applies the Rotate, Translate and Scale transforms:
private void ProcessManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
if (this.MultiTouchEnabled)
{
TranslateTransform _translate = (TranslateTransform)GetTemplateChild("_translate");
if (_translate != null)
{
_translate.X += e.TranslationDelta.Width;
_translate.Y += e.TranslationDelta.Height;
}
RotateTransform _rotate = (RotateTransform)GetTemplateChild("_rotate");
if (_rotate != null)
_rotate.Angle += e.RotationDelta * 180 / Math.PI;
ScaleTransform _scale = (ScaleTransform)GetTemplateChild("_scale");
if (_scale != null)
{
_scale.ScaleX *= e.ScaleDelta;
_scale.ScaleY *= e.ScaleDelta;
}
}
}
A dependency property named MultiTouchEnabled is also defined in order to enable and disable the touch features directly using XAML:
public bool MultiTouchEnabled
{
get { return (bool)GetValue(MultiTouchEnabledProperty); }
set { SetValue(MultiTouchEnabledProperty, value); }
}
public static readonly DependencyProperty MultiTouchEnabledProperty =
DependencyProperty.Register("MultiTouchEnabled", typeof(bool), typeof(MultiTouchView), null);
The usage of this custom control is very simple, just wrap the code you want to touch-enable in this way:
<Window x:Class="WpfMultiTouch.MultiTouchWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/ presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF Multi Touch gestures example" Width="1280" Height="800"
xmlns:myControls="clr-namespace:MultiTouch.Controls.WPF; assembly=MultiTouch.Controls.WPF"
>
<Canvas Background="Black">
<myControls:MultiTouchView MultiTouchEnabled="True">
<myControls:MultiTouchView.Template>
<ControlTemplate>
<Canvas x:Name="_touchArea">
<Viewbox RenderTransformOrigin="0.5, 0.5">
<Image Source="Images/image.png" Width="500"/>
<Viewbox.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="_rotate" Angle="0"/>
<ScaleTransform x:Name="_scale" ScaleX="1" ScaleY="1"/>
<TranslateTransform x:Name="_translate" X="0" Y="0"/>
</TransformGroup>
</Viewbox.RenderTransform>
</Viewbox>
</Canvas>
</ControlTemplate>
</myControls:MultiTouchView.Template>
</myControls:MultiTouchView>
</Canvas>
</Window>
This approach is very powerful, it’s possible to enable multi-touch gestures by simply wrapping the objects inserted in the XAML code inside the MultiTouchView custom control.
The source code is available on Codeplex, including a basic Silverlight 3 implementation using the new touch APIs and behaviors.