Improve the performance of a panel OnMouseMove method for a signature control

谁都会走 提交于 2019-12-24 10:49:14

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!