如何绘制更新行

时间:2016-07-16 18:33:04

标签: c# drawing line

我的目标非常简单。想象一下,打开MSPaint,单击线条工具,按住鼠标,然后拖动它。它会锚定您单击鼠标的起始坐标,并不断绘制并重新绘制一条线到当前位置。

除了我在C#中尝试这样做之外并没有像我希望的那样好。

[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);
}

以这种方式使用它,我只获得一次绘制的线条。但是,如果我将DrawLine()移动到像MouseUp这样的更静态的事件,它会绘制它,然后在大约四分之一秒后消失。

在这里实现目标的最佳方式是什么?

我认为无论使用什么事件来使线条消失,我都希望首先将线条的绘图附加到其中。

1 个答案:

答案 0 :(得分:1)

您需要进行两次绘图调用:

  • 使用MouseMove

  • someControls.CreateGraphics的光标后面的非持续行
  • 另一个持久行,在MouseUp中触发,其中

    • 存储坐标和
    • 在画布控件上调用Invalidate
    • 使用其Paint对象绘制画布的e.Graphics事件。

这是一个最小的示例代码:

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());
}

请注意,这使用PictureBox作为画布控件。它是用于此类交互的控件。您的代码似乎会绘制到不属于您的桌面上。以持久的方式绘制它并不像使用/ any Paint应用程序那样。

另请注意,我的示例存储了一个点列表,并将它们绘制为一个非闭合折线。为DrawLines绘制已关闭交换DrawPolygon!要绘制几个这样的折线或多边形,您需要..

  • ..决定用户界面,可能添加分段点仅在按下控制键否则完成当前折线
  • 将积分存储在List<List, Point>>

另请注意,这是要求使用control.CreateGraphics罕见示例之一,因为您实际上想要非持久性绘图用户移动鼠标。

大多数情况下,Winforms图形基本规则#1适用:

永远不要使用control.CreateGraphics!永远不要尝试缓存Graphics对象!使用Bitmap bmp或在控件的Graphics g = Graphics.FromImage(bmp)事件中使用Paint参数绘制e.Graphics