如何绘制更新行
我的目标非常简单。 想象一下,打开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.CreateGraphics
在MouseMove
中跟随光标的非持久行 -
另一个用于持久化的行,在
MouseUp
触发,在哪里- 你存储坐标和
- 在canvas控件上调用
Invalidate
- 使用
e.Graphics
对象e.Graphics
canvas的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
。