Windows 7 and WPF 4.0 Multitouch: Touch Points

Update: if you’re looking to just implement standard multitouch gestures, check out my post on manipulation.

One of the most popular posts on this blog is my writeup on getting multitouch events in Windows 7 using WPF and .NET 3.5. Now that .NET 4.0 is in open beta, its time for an update. That’s a lot of periods in two sentences.

Microsoft has made it much easier to access touch events in WPF. The touch events are likened to the mouse events you are likely very comfortable with, but with a little more information in order to support multitouch.

I’ll lay out a full application for you to play with. First, the XAML of the main window class:

<Window x:Class="NewTouchTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" 
        TouchDown="Window_TouchDown" TouchMove="Window_TouchMove" TouchUp="Window_TouchUp">
    <Grid x:Name="AppGrid">
 
    </Grid>
</Window>

Did you see that? I hooked up multitouch events in my XAML. GAME CHANGER.

Yes, it is that easy. You are already set up to receive touch events. Wizardry!

Now, let’s do something worthwhile with our new found power. This application will create squares for every touch point and show its associated ID. This kind of application is useful when messing with new hardware to see how accurate the touch is. It is basically an expanded version of the last example, supporting INFINITE touch points. Infinite up to a certain power of 2, anyway.

We’ll start with an array of colors to choose from for our infinite points.

public partial class MainWindow : Window
{
    Brush[] ColorList = new Brush[] { Brushes.Black, Brushes.Yellow, Brushes.Turquoise, Brushes.Purple, Brushes.Orange, Brushes.Navy, Brushes.Pink, Brushes.Brown, Brushes.DarkKhaki };
    public MainWindow()
    {
        InitializeComponent();
    }

Upon the first touch, we create a new Border and move it to the corresponding location using a TranslateTransform. We also create a child TextBlock in order to display the touch point’s ID.

The ID is very important when doing something more interesting with multitouch, as it signifies a unique finger. If you are coding any gestures, you’ll need to make sure you keep track of your fingers. Actually, that’s probably a pretty sound piece of advice for life in general.

    private void Window_TouchDown(object sender, TouchEventArgs e)
    {
        Border newTouch = new Border();
        TextBlock idText = new TextBlock();
        int id = e.GetTouchPoint(this).TouchDevice.Id;
        idText.Text = id.ToString();
        idText.Foreground = Brushes.White;
        newTouch.Child = idText;
        newTouch.Background = ColorList[id % ColorList.Length];
        newTouch.Width = 20;
        newTouch.Height = 20;
        newTouch.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
        newTouch.VerticalAlignment = System.Windows.VerticalAlignment.Top;
        AppGrid.Children.Add(newTouch);
        Point touchLoc = e.GetTouchPoint(this).Position;
        newTouch.RenderTransform = new TranslateTransform(touchLoc.X, touchLoc.Y);
    }

We update the position on every subsequent move event, finding the associated Border by its child TextBlock.

    private void Window_TouchMove(object sender, TouchEventArgs e)
    {
        foreach (UIElement child in AppGrid.Children)
        {
            if (child is Border)
            {
                TouchPoint touch = e.GetTouchPoint(this);
                if (((TextBlock)((Border)child).Child).Text == touch.TouchDevice.Id.ToString())
                {
                    Point touchLoc = touch.Position;
                    child.RenderTransform = new TranslateTransform(touchLoc.X, touchLoc.Y);
                    break;
                }
            }
        }
    }

After the touch is released, we remove the associated border.

    private void Window_TouchUp(object sender, TouchEventArgs e)
    {
        foreach (UIElement child in AppGrid.Children)
        {
            if (child is Border)
            {
                TouchPoint touch = e.GetTouchPoint(this);
                if (((TextBlock)((Border)child).Child).Text == touch.TouchDevice.Id.ToString())
                {
                    AppGrid.Children.Remove(child);
                    break;
                }
            }
        }
    }
}

There. Easy! Keep an eye out for a post regarding the new gesture events.

One thought on “Windows 7 and WPF 4.0 Multitouch: Touch Points

  1. Pingback: WPF 4.0 Multitouch: Manipulation | Between the Lines

Comments are closed.