update move mouse

169 views Asked by At

I met a question about the efficiency of GDI+. There are several variables and methods as below: 1.Points, such as A(Represents a coordinate point, such as X Y Z), B, C, D, E, etc.

2 List named Cmd1, used to add points by thread

3.Paint method, in this method, the set of points connected to the line

4.Thread for the constant addition of new points,such as F,G,H,I,J etc.

In Paint Method,i use g.DrawLine() to link a and b,c,d,e. In thread,when i add new points,i will call invalid to refresh component. so my question is,points become more and more, how can I maintain high efficiency, and redraw,

do not start from the a point to re - drawline.

Sub DrawGLines2(g As Graphics)

    g.SmoothingMode = SmoothingMode.HighSpeed
    Dim Pen As New Pen(Brushes.White)
    Dim i As Int32
    'Dim c As Int32
    Dim preCmd1 As Cmd1
    Try
        For Each cmd As Cmd1 In Cmd1s            
                Dim pfs() As PointF = cmd.PointFs.ToArray
                If preCmd1 IsNot Nothing Then
                    g.DrawLine(Pen, cmd.PointFs(0), preCmd1.PointFs(0))
                End If
                preCmd1 = cmd
            End If

        Next
    Catch ex As Exception
        Debug.Print(ex.Message)
    End Try
End Sub

Private Sub Sheet_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    If Me.Cmd1s.Count>0 Then
        DrawGLines2(e.Graphics) 
    End If
End Sub

Public Sub AddPoint(x As Double, y As Double, z As Double, Optional G As Int32 = -1)
    Dim cmd1 As DrvSimu.Cmd1 = Nothing
    If cmd1 Is Nothing Then
        cmd1 = New DrvSimu.Cmd1
        Me.Cmd1s.Add(cmd1)
    End If

    Dim pf3d As New PointF3D(x, y, z)
    cmd1.PointF3Ds.Add(pf3d)

    Me.Invalidate()

End Sub

The thread will call AddPoint to add a,b,c,d,e points,and use invalid method to refresh,when i call invalid,the "For Each cmd As Cmd1 In Cmd1s" for each will begin from A point,so when points become more and more, how can I maintain high efficiency, and redraw, do not start from A point to re - drawline

1

There are 1 answers

5
Thomas Voß On

It depends, what you exactly want to do.

One possibility is the one you are currently using. On each invalidate you redraw all lines. Depending on the drawing quality and cpu you can draw more or less lines but it should be possible to draw at least 10 lines per ms.

If you only add lines and you don't need to remove or modify them you could also draw all lines to a bitmap and on invalidate you only draw that image to the screen. By this you only need to draw the new lines to the picture when they are added. The problem with this method is that you still need a full redraw if you want to zoom or pan the area or if you want to remove lines.

As a starting point see the Graphics.FromImage(...) method. Use the Pixelformat Format32bppARGB for best performace.

Edit:

public partial class LineForm : Form
{
    private Bitmap lineBitmap = null;

    private List<Tuple<PointF,PointF>> lines = new List<Tuple<PointF,PointF>>();

    private List<Tuple<PointF,PointF>> newLines = new List<Tuple<PointF,PointF>>();

    // must be set if you remove line, pan or zoom the view and if you resize the form.
    private bool redrawAll = false;

    public LineForm()
    {
        this.Paint += new System.Windows.Forms.PaintEventHandler(this.OnPaint);
        this.Resize += new System.EventHandler(this.OnResize);
    }

    private void OnResize(object sender, EventArgs e)
    {
        if (this.lineBitmap!= null)
        {
            this.lineBitmap.Dispose();
        }

        if (this.Width <= 0 || this.Height <= 0)
        {
            return;
        }

        this.lineBitmap = new Bitmap(this.Width, this.Height, PixelFormat.Format32bppPArgb);
        this.redrawAll = true;
    }

    private void OnPaint(object sender, PaintEventArgs e)
    {
        Graphics lineGfx = Graphics.FromImage(this.lineBitmap);
        // Settings for best drawing Performance. Must be adjusted for better quality
        lineGfx.CompositingQuality = CompositingQuality.HighSpeed;
        lineGfx.InterpolationMode = InterpolationMode.NearestNeighbor;
        lineGfx.SmoothingMode = SmoothingMode.None;
        lineGfx.PixelOffsetMode = PixelOffsetMode.None;
        lineGfx.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
        lineGfx.CompositingMode = CompositingMode.SourceCopy;

        // Only clear the Image and draw all lines if necessary
        if(this.redrawAll)
        {
            lineGfx.Clear(Color.Transparent);
            foreach(Tuple<PointF,PointF> line in this.lines)
            {
                lineGfx.DrawLine(Pens.Black, line.Item1, line.Item2);
            }
        }

        // Draw the new Lines to the Bitmap and store them to lines list
        foreach(Tuple<PointF,PointF> newline in this.newLines)
        {
            lineGfx.DrawLine(Pens.Black, newline.Item1, newline.Item2);
            tihs.lines.Add(newLine);
        }

        // Clear the newLines List as the liones are added to the lines List now.
        this.newLines.Clear();

        // Draw the Bitmap to the screen
        e.Graphics.DrawImageUnscaled(this.lineBitmap,0,0);
    }

    private void AddLine(PointF p1, PointF p2)
    {
        this.newLines.Add(new Tuple<PointF,PointF>(p1,p2));
        // Invalidate the view => OnPaint Event is raised;
        this.Invalidate();
    }
}

Note: I haven't added any lock mechanism to the List operations. To prevent changes to the lists while using them you should add some locks.