如何绘制更新行

我的目标非常简单。 想象一下,打开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这样的更静态的事件,它将绘制它,然后在大约四分之一秒后消失。

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

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

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

  • 一个用于使用someControls.CreateGraphicsMouseMove中跟随光标的非持久行

  • 另一个用于持久化的行,在MouseUp触发,在哪里

    • 你存储坐标和
    • 在canvas控件上调用Invalidate
    • 使用e.Graphics对象e.Graphicscanvas的Paint事件。

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

 List allPoints = new List(); 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作为canvas控件。 它是用于这种交互的控制。 您的代码似乎会绘制到不属于您的桌面上。 以持久的方式绘制它并不像使用/ any Paint应用程序那样。

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

  • ..在用户界面上确定它,可能只在按下控制键添加分段点, 否则完成当前折线
  • 将点存储在List>

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

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

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