c#通过拖动绘制线

c#通过拖动绘制线,c#,winforms,user-interface,drawing,gdi+,C#,Winforms,User Interface,Drawing,Gdi+,如何像windows绘制一样绘制一条线,单击固定的第一个点,然后第二个点(以及该线)用鼠标移动,再单击一次将修复该线 int x = 0, y = 0; protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); // Create the graphics object Graphics g = CreateGraphics(); // Create the pen t

如何像windows绘制一样绘制一条线,单击固定的第一个点,然后第二个点(以及该线)用鼠标移动,再单击一次将修复该线

int x = 0, y = 0;
protected override void OnMouseMove(MouseEventArgs e)
{
    base.OnMouseMove(e);
    // Create the graphics object
    Graphics g = CreateGraphics();
    // Create the pen that will draw the line
    Pen p = new Pen(Color.Navy);
    // Create the pen that will erase the line
    Pen erase = new Pen(Color.White);
    g.DrawLine(erase, 0, 0, x, y);
    // Save the mouse coordinates
    x = e.X; y = e.Y;
    g.DrawLine(p, 0, 0, x, y);
}
单击事件部分很好,但使用上述方法,擦除线实际上是白线,与其他背景图像和先前绘制的蓝线重叠


有没有更易于管理的方法来实现这一点?谢谢

不要试图通过在线条上方绘制来擦除线条。如果您绘制到一个屏幕外缓冲区,并在每次绘制时调用将位图绘制到控件,则会更好。这样,您将获得无闪烁的图形和一条干净的线条,它的工作方式正是您想要的


请看一看有关如何使用
Graphics
类以及如何进行一般绘图的详细说明。在文章的最后还有一个很好的示例程序。我建议您在阅读说明后查看该源代码。

表单客户端区域上的任何绘图都应在OnPaint事件中实现,以避免任何奇怪的效果。 考虑下面的代码片段:

Point Latest { get; set; }

List<Point> _points = new List<Point>(); 

protected override void OnMouseMove(MouseEventArgs e)
{
    base.OnMouseMove(e);

    // Save the mouse coordinates
    Latest = new Point(e.X, e.Y);

    // Force to invalidate the form client area and immediately redraw itself. 
    Refresh();
}

protected override void OnPaint(PaintEventArgs e)
{
    var g = e.Graphics;
    base.OnPaint(e);

    if (_points.Count > 0)
    {
        var pen = new Pen(Color.Navy);
        var pt = _points[0];
        for(var i=1; _points.Count > i; i++)
        {
            var next = _points[i];
            g.DrawLine(pen, pt, next);
            pt = next;
        }

        g.DrawLine(pen, pt, Latest);
    }
}

private void Form1_MouseClick(object sender, MouseEventArgs e)
{
    Latest = new Point(e.X, e.Y);
    _points.Add(Latest);
    Refresh();
}
pointlatest{get;set;}
列表_点=新列表();
MouseMove上的受保护覆盖无效(MouseEventArgs e)
{
基地移动(e);
//保存鼠标坐标
最新=新点(e.X,e.Y);
//强制使表单客户端区域无效,并立即重新绘制自身。
刷新();
}
受保护的覆盖无效OnPaint(PaintEventArgs e)
{
var g=e.图形;
基础漆(e);
如果(_points.Count>0)
{
var笔=新笔(颜色为海军);
var pt=_点[0];
对于(变量i=1;_points.Count>i;i++)
{
var next=_点[i];
g、 抽绳(pen、pt、next);
pt=下一个;
}
g、 抽绳(pen,pt,最新);
}
}
private void Form1\u鼠标单击(对象发送方,鼠标目标e)
{
最新=新点(e.X,e.Y);
_加分(最新);
刷新();
}

以后是否要保存生成的图像?谢谢,我刚刚试过。它非常整洁,但是使用Refresh方法,它不保留前面的行。一旦我开始一个新的线条图,前一个将消失。有没有办法保留所有以前的行?然后您可以将OnClick()事件中的所有以前的点保存在列表中,然后从OnPaint()中绘制。请参阅上面答案中更新的代码片段。要消除闪烁效果,必须将窗体上的Double Buffered属性设置为True。这是什么OnPaint?当我查看事件时,例如表单上的事件,我看到它被称为Form1_Paint