hello everyone,
My M.Sc. project is to develop a handwritten character recognizer for
my language 'Sinhala.' As the first step I need to develop a
application to capture online handwritten character data. For this
purpose, I examined the "Pocket PC Signature Application
Sample" [http://msdn2.microsoft.com/en-us/library/aa446559.aspx] and
tried to modify it.
Exactly, at this moment my requirement is to collect stylus
coordinates(x,y) every 10 milliseconds when a stroke is drawn in the
pocket pc touch screen (in a specific area). i.e. All I need is a
series of [X,Y, Time] information for each stroke.
e.g.
STROKE #1
X Y Time
12,12,1
12,13,2
14,13,3
.
.
To achieve this I've modified the SingatureControl class in the above
example, but it did not work as I expected. (Every time I redraw a
stroke, it draws two other funny strokes!) Can you please guide me how
to correct this problem, or please advice me how to achieve this task?
Following is the code, that I've modified. But it does not give the
expected output. As the clock-triggering event and the moveMove events
are separated, I've no idea how to get the coordinates of mouse
pointer when timer triggers at 10milliseconds interval.
Thank you in advance,
Regards,
Asanka
/*
SignatureControl class
--
Collects and displays a signature. The signature is made up of
a list of line segments. Each segment contains an array of points
(x and y coordinates).
Draws to a memory bitmap to prevent flickering.
Raises the SignatureUpdate event when a new segment is added to
the signature.
*/
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using Common;
namespace PocketSignature
{
/// <summary>
/// Custom control that collects and displays a signature.
/// </summary>
public class SignatureControl : Control
{
// Timer
Timer clock= new Timer();
int time = 0;
int tx, ty = 0; // holds the mouse pointer position
// gdi objects
Bitmap _bmp;
Graphics _graphics;
Pen _pen = new Pen(Color.Black);
// list of line segments(strokes)
ArrayList _lines = new ArrayList();
ArrayList timeseg = new ArrayList(); //time
information for each stroke.
// the current line segment (stroke)
ArrayList _points = new ArrayList();
ArrayList _times = new ArrayList(); //time
information of current stroke
Point _lastPoint = new Point(0,0);
// if drawing signature or not
bool _collectPoints = false;
// notify parent that line segment was updated
public event EventHandler SignatureUpdate;
/// <summary>
/// List of signature line segments.
/// </summary>
public ArrayList Lines
{
get { return _lines; }
}
/// <summary>
/// List of signature line time segments.
/// </summary>
public ArrayList Times
{
get { return timeseg; }
}
/// <summary>
/// Return the signature flattened to a stream of bytes.
/// </summary>
public byte[] SignatureBits
{
get { return SignatureData.GetBytes(this.Width, this.Height,
_lines); }
}
public SignatureControl()
{
clock = new Timer();
clock.Interval = 1;
clock.Tick += new EventHandler(clock_Tick) ;
}
protected override void OnPaint(PaintEventArgs e)
{
// blit the memory bitmap to the screen
// we draw on the memory bitmap on mousemove so there
// is nothing else to draw at this time (the memory
// bitmap already contains all of the lines)
CreateGdiObjects();
e.Graphics.DrawImage(_bmp, 0, 0);
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// don't pass to base since we paint everything, avoid flashing
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
time = 0; //
reset time count
// process if currently drawing signature
if (!_collectPoints)
{
// start collecting points
// use current mouse click as the first point
_lastPoint.X = e.X;
_lastPoint.Y = e.Y;
// this is the first point in the list
_points.Clear();
_times.Clear();
_points.Add(_lastPoint);
_times.Add(time);
_collectPoints = true;
clock.Enabled = true; //start
clock
}
}
private void clock_Tick(object sender, System.EventArgs e)
{
time++;
int x, y = 0;
if (_collectPoints)
{
// add point to current line segment
x=tx; //MousePosition.X;
y=ty; //MousePosition.Y;
_points.Add(new Point(x, y));
_times.Add(time);
// draw the new segment on the memory bitmap
_graphics.DrawLine(_pen, _lastPoint.X, _lastPoint.Y, x, y);
// update the current position
_lastPoint.X = x;
_lastPoint.Y = y;
// display the updated bitmap
Invalidate();
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
// process if drawing signature
if (_collectPoints)
{
// stop collecting points
_collectPoints = false;
clock.Enabled = false;
time = 0;
// add current line to list of segments
Point[] points = new Point[_points.Count];
int[] timesg = new int[_points.Count];
for (int i=0; i < _points.Count; i++)
{
Point pt = (Point)_points[i];
int t = (int) _times[i];
points[i].X = pt.X;
points[i].Y = pt.Y;
timesg[i] = t;
}
_lines.Add(points);
timeseg.Add(timesg);
// start over with a new line
_points.Clear();
_times.Clear();
// notify container a new segment was added
RaiseSignatureUpdateEvent();
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (_collectPoints)
{
tx = e.X;
ty = e.Y;
}
}
/// <summary>
/// Clear the signature.
/// </summary>
public void Clear()
{
_lines.Clear();
timeseg.Clear();
InitMemoryBitmap();
Invalidate();
}
/// <summary>
/// Create any GDI objects required to draw signature.
/// </summary>
private void CreateGdiObjects()
{
// only create if don't have one or the size changed
if (_bmp == null || _bmp.Width != this.Width || _bmp.Height !=
this.Height)
{
// memory bitmap to draw on
InitMemoryBitmap();
}
}
/// <summary>
/// Create a memory bitmap that is used to draw the signature.
/// </summary>
private void InitMemoryBitmap()
{
// load the background image
_bmp = Global.LoadImage("sign here.png");
// get graphics object now to make drawing during mousemove faster
_graphics = Graphics.FromImage(_bmp);
}
/// <summary>
/// Notify container that a line segment has been added.
/// </summary>
private void RaiseSignatureUpdateEvent()
{
if (this.SignatureUpdate != null)
SignatureUpdate(this, EventArgs.Empty);
}
}
}