问题
I have a Windows Mobile application (C#, .Net framework 2), the codebase of which is also now being used to run on Windows 7 and Windows 8. One of the controls that we wrote for this application is a scribble control that allows the user to capture a signature. This control works ok on Windows Mobile and can be used to capture signatures fairly well. On Windows, however, the OnMouseMove
override method of a panel control is too slow, or called to infrequently, and the signature becomes very "blocky". So, for example, if you try capture a circle, on Windows Mobile you get a reasonable circle, but on Windows you end up getting a square because mousemove
is not called frequently enough. Here is the OnMouseMove
override method of the panel:
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (!_captureMouseCoordinates) { return; }
LineToDraw line = new LineToDraw();
line.StartX = _lastMouseCoordinates.X;
line.StartY = _lastMouseCoordinates.Y;
line.EndX = e.X;
line.EndY = e.Y;
_points.Add(line);
_graphicsHandle.DrawLine(_scribblePen, line.StartX, line.StartY, line.EndX, line.EndY);
// Refresh rectangle for the line drawn
Point leftCorner = new Point();
Size rectangleSize = new Size();
// Case 1: line down, right
if (line.StartX <= line.EndX && line.StartY <= line.EndY)
{
leftCorner.X = line.StartX;
leftCorner.Y = line.StartY;
}
// Case 2: Line up, right
if (line.StartX <= line.EndX && line.StartY >= line.EndY)
{
leftCorner.X = line.StartX;
leftCorner.Y = line.EndY;
}
// Case 3: Line up, left
if (line.StartX >= line.EndX && line.StartY >= line.EndY)
{
leftCorner.X = line.EndX;
leftCorner.Y = line.EndY;
}
// Case 4: Line down, left
if (line.StartX >= line.EndX && line.StartY <= line.EndY)
{
leftCorner.X = line.EndX;
leftCorner.Y = line.StartY;
}
rectangleSize.Height = Math.Abs(line.EndY-line.StartY)+1;
rectangleSize.Width = Math.Abs(line.EndX-line.StartX)+1;
// save last mouse co-ordinates
_lastMouseCoordinates.X = line.EndX;
_lastMouseCoordinates.Y = line.EndY;
Invalidate(new Rectangle(leftCorner.X,leftCorner.Y, rectangleSize.Width, rectangleSize.Height));
}
The _captureMouseCoordinates boolean member variable in the code above is being set on the 'mousedown' event handler.
I notice that if I comment out the invalidate in this method and only invalidate on mouseup
that the signature then is much smoother, but then you don't get to see the signature while it is being drawn. Does anyone have any ideas how I could go about getting this signature control to perform better so that the signatures produced by it are smoother and yet still be able to give feedback to the user as the lines are being drawn.
回答1:
I don't know where _graphicsHandle is - but you should generally never save Graphics objects. Let all rendering be in Invalidate().
Create two collections:
List<Point> _currentStroke
List<List<Point>> _allStrokes
MouseMove:
_currentStroke.Add(e.Location)
MouseUp
_allStrokes.Add(_currentStroke)
On each OnPaint
foreach(var stroke in _allStrokes)
{g.DrawLines(pen, stroke.ToArray());}
if(_currentStroke.Count > 1)
g.DrawLines(pen, _currentStroke)
(Obviously add all supporting code).
You should have no performance issues.
来源:https://stackoverflow.com/questions/14710643/improve-the-performance-of-a-panel-onmousemove-method-for-a-signature-control