Click here to Skip to main content
15,891,136 members
Articles / Multimedia / GDI+

C# Application to Create and Recognize Mouse Gestures (.NET)

Rate me:
Please Sign up or sign in to vote.
4.82/5 (39 votes)
17 Mar 2008CPOL5 min read 221.7K   8.1K   144  
This program can create and recognize mouse gestures.
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Media;
using MouseGestures;
using NeuralNetworks;

namespace GestureRecognizer
{
	public partial class GestureMainForm : Form
	{
		public enum ActionMode
		{ 
			Acquiring = 0,
			Training = 1,
			Recording = 2,
			AutoCreatingTrainingSet = 3,
			ManualCreatingGestureSet = 4,
			Verifing = 5
		}

		public enum MouseActionType
		{
			None = 0,
			Recording = 1
		}

		[Browsable(true), Category("Event"), Description("Event inovked on gesture drawn.")]
		public event OnGestureDrawnDelegate GestureDrawn;

		protected int m_MaxErrors;
		protected double m_MaxError;
		protected double m_MinError;
		protected List<double> m_Errors;
		protected Gesture[] m_CreatedGestures;
		protected int m_GesturesToCreate;
		protected int m_GesturesCreated;
		protected GestureRecognizerData m_DataToCreateSetTo;
        protected GestureSet m_GestureSetToCreate;
		protected NeuralNetworks.PerformanceMonitor[] m_Monitors;
		protected int m_Index;
		protected bool m_Replace;

		private ActionMode m_Action;
		private MouseActionType m_MouseAction;
		private List<PointF> m_Points;
		private Pen m_GesturePen;
		private SolidBrush m_PointsBrush;
		private Pen m_GridPen;
		private int m_GridWidth;
		private int m_GridHeight;
		protected Dictionary<string, GestureRecognizerData> m_GesturesData;

		[Browsable(true), Category("Behavior"), Description("Grid pen color.")]
		public Color GridPenColor { get { return m_GridPen.Color; } set { m_GridPen = new Pen(value, 1); Refresh(); } }

		[Browsable(true), Category("Behavior"), Description("Grid width.")]
		public int GridWidth { get { return m_GridWidth; } set { m_GridWidth = value; Refresh(); } }

		[Browsable(true), Category("Behavior"), Description("Grid height.")]
		public int GridHeight { get { return m_GridHeight; } set { m_GridHeight = value; Refresh(); } }

		[Browsable(true), Category("Behavior"), Description("Gesture color.")]
		public Color GestureColor { get { return m_GesturePen.Color; } set { m_GesturePen = new Pen(value, 1); Refresh(); } }

		[Browsable(true), Category("Behavior"), Description("Gesture thickness.")]
		public decimal GestureThickness { get { return (decimal)m_GesturePen.Width; } set { m_GesturePen.Width = (float)value; Refresh(); } }

		[Browsable(true), Category("Behavior"), Description("Points color.")]
		public Color PointsColor { get { return m_PointsBrush.Color; } set { m_PointsBrush = new SolidBrush(value); Refresh(); } }

		public ActionMode Action { get { return m_Action; } }

		public Dictionary<string, GestureRecognizerData> GesturesData { get { return m_GesturesData; } }

		public GestureMainForm()
		{
			SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
			DoubleBuffered = true;

			InitializeComponent();

			m_GesturePen = new Pen(Color.Red, 1);
			m_PointsBrush = new SolidBrush(Color.Blue);
			m_GridPen = new Pen(Color.LightGray, 1);
			m_GridWidth = 20;
			m_GridHeight = 20;
			m_Points = new List<PointF>();

			m_MouseAction = MouseActionType.None;
			m_Action = ActionMode.Acquiring;

			m_GesturesData = new Dictionary<string, GestureRecognizerData>();
			m_GesturesToCreate = 0;
			m_GesturesCreated = 0;
			m_MaxErrors = (int)Properties.Settings.Default.MaximumEpochs;
			m_MaxErrors = -1;
			m_MinError = -1;
			m_Errors = new List<double>();
			m_Index = -1;
			m_Replace = true;
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			base.OnPaint(e);

			DrawGrid(e.Graphics);
			DrawPoints(e.Graphics);
			DrawGraph(e.Graphics);
		}

		#region Drawing functions...
		private void DrawGraph(Graphics g)
		{
			if (m_Action == ActionMode.Training)
			{
				float pass = 0;
				if (m_MaxErrors > (ClientSize.Width - 20f))
					pass = (ClientSize.Width - 20f) / (float)m_MaxErrors;
				else
					pass = 1;

				float base_height = ClientSize.Height - 30f, y;

				for (int h = 0; h < m_Errors.Count; h++)
				{
					y = base_height - (base_height - 120) * (float)(m_Errors[h] / m_MaxError);
					g.DrawLine(m_GesturePen, h * pass, ClientSize.Height - 30, h * pass, y);
				}
			}
		}

		private void DrawGrid(Graphics g)
		{
			int i;
			int max = ClientSize.Width / m_GridWidth;
			float size;
			for (i = 1; i <= max; i++)
			{
				size = m_GridWidth * i;
				g.DrawLine(m_GridPen, size, 0, size, ClientSize.Height);
			}

			max = ClientSize.Height / m_GridHeight;
			for (i = 1; i <= max; i++)
			{
				size = m_GridHeight * i;
				g.DrawLine(m_GridPen, 0, size, ClientSize.Width, size);
			}
		}

		private void DrawPoints(Graphics g)
		{
			if (m_Points.Count >= 2)
			{
				//SystemSounds.Beep.Play();
				PointF[] pts = new PointF[m_Points.Count];
				m_Points.CopyTo(pts, 0);

				//Draw lines by DrawLines function
				g.DrawLines(m_GesturePen, pts);

				//If user-drawing has ended, the program draws anchor ponints
				//(points retrieved by mouse polling)
				if (m_MouseAction == MouseActionType.None)
				{
					foreach (PointF p in pts)
						g.FillRectangle(m_PointsBrush, p.X - 1f, p.Y - 1f, 2, 2);
				}
			}
		}
		#endregion

		protected void OnEpochEnded(double error)
		{
			m_Errors.Add(error);

			if (m_Errors.Count == 1)
			{
				m_MaxError = error;
				m_MinError = error;
			}
			else
			{
				m_MaxError = Math.Max(m_MaxError, error);
				m_MinError = Math.Min(m_MinError, error);
			}
		}

		#region Mouse management...
		protected override void OnMouseDown(MouseEventArgs e)
		{
			if (m_Action != ActionMode.Training && m_Action!= ActionMode.AutoCreatingTrainingSet)
			{
				if (e.Button == MouseButtons.Right)
				{
					if (m_Action == ActionMode.ManualCreatingGestureSet)
						Clear(false);
					else
						Clear();

					m_MouseAction = MouseActionType.Recording;

					Refresh();
					//Invalidate();
				}
			}
		}

		protected override void OnMouseUp(MouseEventArgs e)
		{
			if (m_Action != ActionMode.Training && m_Action != ActionMode.AutoCreatingTrainingSet)
			{
				if (e.Button == MouseButtons.Right)
				{
					m_MouseAction = MouseActionType.None;

					PointF[] points = m_Points.ToArray();

					if (GestureDrawn != null)
						GestureDrawn(points);

					Refresh();
					//Invalidate();

					OnGestureDrawn(points);
				}
			}
		}

		protected override void OnMouseMove(MouseEventArgs e)
		{
			if (m_Action != ActionMode.Training && m_Action != ActionMode.AutoCreatingTrainingSet)
			{
				if (m_MouseAction == MouseActionType.Recording)
				{
					m_Points.Add(e.Location);

					ShowMessage("Drawn points: " + m_Points.Count.ToString(), MessageType.Normal);

					Refresh();
					//Invalidate();
				}
			}
		}
		#endregion

		public void OnNewGestureCreate()
		{
			ShowMessage("Creating new gesture...", MessageType.Normal);
			m_Action = ActionMode.Recording;
		}

		public void OnNewGestureCreated()
		{
			m_Action = ActionMode.Acquiring;
		}

		protected virtual void OnGestureDrawn(PointF[] points)
		{
		
		}

		public void Clear(bool propagate)
		{
			m_Points = new List<PointF>();
			m_Errors = new List<double>();

			if(propagate)
				OnClear();

			Refresh();
		}

		public void Clear()
		{
			Clear(true);
		}

		public virtual void OnClear()
		{
			
		}

		public void AutoCreateGestureSet(GestureRecognizerData data, GestureSet set, int how_many, int index, bool replace)
		{
			ShowInfos("Gestures created: 0/" + how_many.ToString(), MessageType.Normal);
			ShowMessage("Creating gesture set...", MessageType.Normal);
			m_DataToCreateSetTo = data;
            m_GestureSetToCreate = set;
			m_GesturesToCreate = how_many;
			m_GesturesCreated = 0;
			m_Action = ActionMode.AutoCreatingTrainingSet;
			m_CreatedGestures = new Gesture[how_many];
			m_Index = index;
			m_Replace = replace;
			OnAutoCreatingGestureSet();
		}

		protected virtual void OnAutoCreatingGestureSet()
		{ 
		
		}

		public void StartVerifying()
		{
			ShowMessage("Verifying...", MessageType.Normal);
			m_Action = ActionMode.Verifing;
		}

		protected virtual void OnVerifyingStarted()
		{

		}

		public void EndVerifying()
		{
			ShowMessage("Ready", MessageType.Normal);
			m_Action = ActionMode.Acquiring;
			Clear();
		}

		public void StartTraining()
		{
			m_MaxErrors = (int)Properties.Settings.Default.MaximumEpochs;
			m_MaxErrors = -1;
			m_MinError = -1;
			m_Errors = new List<double>();

			m_Action = ActionMode.Training;
		}

		protected virtual void OnTrainingStarted()
		{

		}

		public void EndTraining()
		{
			m_Action = ActionMode.Acquiring;
		}

		public void ManualCreateGestureSet(GestureRecognizerData data, GestureSet set, int how_many, int index, bool replace)
		{
			ShowMessage("Creating gesture set...", MessageType.Normal);
			ShowInfos("Gestures created: 0/" + how_many.ToString(), MessageType.Normal);
			m_DataToCreateSetTo = data;
            m_GestureSetToCreate = set;
			m_GesturesToCreate = how_many;
			m_GesturesCreated = 0;
			m_Action = ActionMode.ManualCreatingGestureSet;
			m_CreatedGestures = new Gesture[how_many];
			m_Index = index;
			m_Replace = replace;
			OnManualCreatingGestureSet();
		}

		protected virtual void OnManualCreatingGestureSet()
		{

		}

		protected void OnGestureSetCreated()
		{
			m_Action = ActionMode.Acquiring;
		}

		public virtual void ShowMessage(string message, MessageType type)
		{

		}

		public virtual void ShowInfos(string[] messages, MessageType type)
		{

		}

		public virtual void ShowInfos(string messages, MessageType type)
		{

		}
	}
}

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
Software Developer (Senior) Apex s.r.l.
Italy Italy
I got my Computer Science (Engineering) Master's Degree at the Siena University (Italy), but I'm from Rieti (a small town next to Rome).
My hobbies are RPG, MMORGP, programming and 3D graphics.
At the moment I'm employed at Apex s.r.l. (Modena, Italy) as a senior software developer, working for a WPF/WCF project in Rome.

Comments and Discussions