Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
102 views
in Technique[技术] by (71.8m points)

c# - How to draw an updating line

My goal is very simple. Imagine opening MSPaint, clicking the line tool, holding mouse down, and dragging it around. It anchors the starting coordinates where you clicked mouse down and constantly draws and redraws a line to your current position.

Except me trying to do this in C# isn't working as well as I would hope.

[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("User32.dll")]
static extern int ReleaseDC(IntPtr hwnd, IntPtr dc);

protected override void OnPaint(PaintEventArgs e)
{
    endingPoint = GetMouseCoords();
    DrawLine(startingPoint, endingPoint);
}

private void DrawLine(Point startingCoords, Point endingCoords)
{
    IntPtr desktop = GetDC(IntPtr.Zero);
    Pen pen = new Pen(Brushes.Red, 3);
    using (Graphics g = Graphics.FromHdc(desktop))
    {
        g.DrawLine(pen, startingCoords.X, startingCoords.Y, endingCoords.X, endingCoords.Y);
        g.Dispose();
    }
    ReleaseDC(IntPtr.Zero, desktop);
}

Using it this way, I only get the line drawn once. However, if I move the DrawLine() to a more static event like MouseUp, it will draw it, then disappear after about a quarter of a second.

What would be the best way to accomplish my goal here?

I would think that whatever event is being used to make the line disappear is what I would want to attach the drawing of the line to in the first place.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to have two drawing calls:

  • One for the non-persistent line that follows the cursor in the MouseMove using someControls.CreateGraphics

  • the other for the persisting line, triggered in the MouseUp, where

    • you store the coordinates and
    • call Invalidate on your canvas control and
    • draw in the Paint event of your canvas using its e.Graphics object.

Here is a minimal example code:

List<Point> allPoints = new List<Point>();
Point mDown = Point.Empty;

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
    mDown = e.Location;
}

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    allPoints.Add(e.Location);
    pictureBox1.Invalidate();
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button.HasFlag(MouseButtons.Left))
    {
        pictureBox1.Refresh();
        using (Graphics G = pictureBox1.CreateGraphics())
            G.DrawLine(Pens.Red, mDown, e.Location);
    }
}

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    if (allPoints.Count > 1) e.Graphics.DrawLines(Pens.Black, allPoints.ToArray());
}

Note that this uses a PictureBox as the canvas control. It is the control meant for this kind of interaction. Your code seems to draw onto the desktop, which doesn't belong to you. Drawing onto it in a persistent manner is not anything like what you would do with the/any Paint application.

Also note that my example stores a list of points and draws them as one non-closed Polyline. To draw them closed exchange DrawLines for DrawPolygon! To draw several such polylines or polygons you need to..

  • ..decide on the user interface for it, maybe add segment points only while the control-key is pressed and otherwise finish the current polyline
  • store the points in a List<List, Point>>

Also note that this is one of the rare examples where using control.CreateGraphics is called for, as you actually do want a non-persistent drawing while the user moves the mouse.

In most other cases the Winforms graphics basic rule #1 applies:

Never use control.CreateGraphics! Never try to cache a Graphics object! Either draw into a Bitmap bmp using a Graphics g = Graphics.FromImage(bmp) or in the Paint event of a control, using the e.Graphics parameter..


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...