Click here to Skip to main content
15,885,806 members
Articles / Desktop Programming / WPF

Gesture Recognition for Touch Devices (Touch Gestures)

Rate me:
Please Sign up or sign in to vote.
4.96/5 (36 votes)
3 Feb 2010CPOL8 min read 138.5K   7.2K   87  
A multi-touch simple and compound gesture recognition implementation for Windows 7 in WPF.
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace TouchGestures
{
    public class GestureTracker
    {
        // a list of all the points which the mouse traversed
        List<Point> points = new List<Point>();
        // a reference for the canvas in MainWindow.xaml
        readonly Canvas canvas;
        // a timer for removing the rectangle boundary from the gesture image
        DispatcherTimer timer = new DispatcherTimer();
        // name of the recognised gesture
        string gesture = string.Empty;
        // randomly generated name for a rectangle
        string rectangleName = string.Empty;

        // prefix img to the gesture name so that we can select which image to highlight
        private string GetImageNameFromGesture
        {
            get
            {
                return (!string.IsNullOrEmpty(gesture))? string.Format("img{0}", gesture) : string.Empty;
            }
        }

        // generate a new guid and replace minus signs from it
        private string GenerateNewGuidLessMinus()
        {
            return Guid.NewGuid().ToString().Replace("-", string.Empty);
        }

        public GestureTracker(Canvas canvasParam)
        {
            canvas = canvasParam;

            // set timer for the highlighting rectangle to 2 seconds
            timer.Interval = TimeSpan.FromSeconds(2);
            timer.Tick += new EventHandler(highlightTimer_Tick);
        }

        public void ProcessDown(Point location)
        {
            // add point to the gesture's points list
            points.Add(location);
        }

        public void ProcessMove(Point location)
        {
            // add point to the gesture's points list
            points.Add(location);
        }

        public void ProcessUp(Point location)
        {
            // add point to the gesture's points list
            points.Add(location);

            // process and recognize the gesture
            gesture = GestureInterpreter.InterpretGesture(points);

            // find coordinates of the image for the recognized gesture
            Point imageCoordinates = FindImageCoordinatesByGesture();
            // add a boundary to the rectangle, so that it gives a highlight effect
            // pass the left and top coordinates of the image
            AddHighlightToImage(imageCoordinates.X, imageCoordinates.Y);
            
            // start a delay for 2 seconds and in the tick event
            // we remove the rectangle (border) from the image
            // which gives a un-highlighting effect
            timer.Start();
        }

        private Point FindImageCoordinatesByGesture()
        {
            // get the image object by using its name
            Image image = canvas.FindName(GetImageNameFromGesture) as Image;
            Point point = new Point(Canvas.GetLeft(image), Canvas.GetTop(image));
            // return the left and top of the image in a point object
            return point;
        }

        // highlight the image by adding a rectangle boundary around it
        private void AddHighlightToImage(double left, double top)
        {
            Rectangle rectangle = new Rectangle();
            // create a random name for this rectangle
            // this is just to ensure that we don't fail while adding/registering the 
            // rectangle as a children of canvas
            rectangleName = string.Format("rect{0}", GenerateNewGuidLessMinus());
            rectangle.Name = rectangleName;

            // set some generic properties
            rectangle.Width = 72;
            rectangle.Height = 72;
            rectangle.StrokeThickness = 2;
            rectangle.RadiusX = 3;
            rectangle.RadiusY = 3;

            // create a random color for this rectangle
            Random random = new Random((int)DateTime.Now.Millisecond);
            SolidColorBrush brush = new SolidColorBrush(Color.FromRgb((byte)random.Next(0, 255), (byte)random.Next(0, 255), (byte)random.Next(0, 255)));
            rectangle.Stroke = brush;

            // set the coordinates of the rectangle
            Canvas.SetLeft(rectangle, left);
            Canvas.SetTop(rectangle, top);
            // register the name of rectangle with canvas
            // and add it to childres list of canvas
            canvas.RegisterName(rectangleName, rectangle);
            canvas.Children.Insert(0, rectangle);
        }

        private void highlightTimer_Tick(object sender, EventArgs e)
        {
            // remove the boundary from the image
            // or actually remove the rectangle that we added earlier from canvas 
            RemoveHighlightFromImage();
            // disable and stop the timer
            timer.Stop();
        }

        // remove the highlight boundary from the image
        // in actual remove the rectangle that we added a few seconds ago
        private void RemoveHighlightFromImage()
        {
            // find the rectangle by the registered name
            Rectangle rectangle = (Rectangle)canvas.FindName(rectangleName);
            // change the color of boundary
            rectangle.Stroke = new SolidColorBrush(Colors.White);
            // remove from childres list and unregister the name
            canvas.Children.Remove(rectangle);
            canvas.UnregisterName(rectangleName);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader
India India

Manoj Kumar is a Humble Programmer and a trainer having dozens of trainings, publications and articles to his wallet.


His programming adventures began with Basic at an age of 11. Being a mathematician at core, soon he started looking for some more and moved to assembly language, later to C, C++, VC++ and finally to .Net.


He started his professional career as a VC++ 6 trainer, moved to embedded systems and device driver development, then to complex biological systems and finally moved to pure application development.


He has been teaching and training people for more than 12 years on a wide range of topics including Mathematics, Algorithms, Data Structures, C, C++, VC++, MFC, C#, Design Patterns and now a days he is working extensively with Visual Studio and .Net framework which includes VSX, WPF, Silverlight, WCF, WF, XAML and RIAs.


Awards:


  • Ideablade RIA Service Challenge winner
  • Visual Studio 2010 Extension Contest winner (Best Use of Editor)


Visit my website and blog or drop me a mail.


Feel free to connect with me on Linkedin.


Comments and Discussions