在窗体上绘制一条连续的线,例如 Winforms C# 上的 MS paint
Drawing a consecutive line on a form like MS paint on Winforms C#
我有一个关于 Graphics 对象的问题。我想像 MS paint 一样画一条连续的线。我不知道如何实现这样的事情。我知道如何从鼠标位置开始一行。我在图片框上执行此操作并添加新点 (e.X, e.Y)。当然,另一条线不能相同,否则将看不到任何线。我无法制作另一个 Point(10, 10) 或类似的东西。因为那样它会始终从同一点创建一条线。
有谁知道如何画连续的直线(带曲线)
是否与mouse_down和mouse_up事件有关?我真的被这个问题困扰了很长时间。如果你们中的任何人有时间向我解释可行的方法,那就太好了!
提前致谢!
大体上:
- 在
MouseDown
上,捕获鼠标并存储当前位置。此位置是您的初始 Point
值。
- 在
MouseMove
上,将当前位置添加到您的点列表中。
- 在
MouseUp
上,根据需要完成曲线,停止捕获鼠标。
渲染时,将 Point
值列表转换为数组并将其传递给 Graphics.DrawLines()
方法。作为一种可能的优化,一旦用户完成绘图,就将列表永久转换为数组。或者,使用 Bitmap
实例作为渲染缓存。
请注意,您可以配置用于绘制线条的 Pen
对象以应用特殊效果,如端盖和斜接接头。
要绘制曲线,请改用Graphics.DrawBeziers()
方法。请注意,在这种情况下,鼠标事件期间捕获的点应该是传递给方法的数组中的每隔三个点。每个点之间的两点是每条曲线的控制点。
您可能应该从 DrawLines()
开始,因为它更简单。一旦你让它工作得很好,那么你就可以使用 DrawBeziers()
方法使你的生活复杂化。至少,您必须自动计算用于该方法的默认控制点。最好给用户一个编辑控制点的方法,这样他们就可以自定义曲线了。
我刚刚为您实现了简单的绘画。只需创建一个新项目并将下面的代码复制到 Form1.cs 文件。代码中的注释应该解释它是如何工作的。
public partial class Form1 : Form
{
private Bitmap bmp; // Place to store our drawings
private List<Point> points; // Points of currently drawing line
private Pen pen; // Pen we will use to draw
public Form1()
{
InitializeComponent();
DoubleBuffered = true; // To avoid flickering effect
bmp = new Bitmap(640, 480); // This is our canvas that will store drawn lines
using (Graphics g = Graphics.FromImage(bmp))
g.Clear(Color.White); // Let's make it white, like paper
points = new List<Point>(); // Here we will remember the whole path
pen = new Pen(Color.Black);
MouseDown += OnMouseDown; // Start drawing
MouseMove += OnMouseMove; // Drawing...
MouseUp += OnMouseUp; // Stop drawing
Paint += OnPaint; // Show the drawing
}
void OnPaint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(bmp, 0, 0); // Show what is drawn
if (points.Count > 0)
e.Graphics.DrawLines(pen, points.ToArray()); // Show what is currently being drawn
}
void OnMouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
points.Clear();
points.Add(e.Location); // Remember the first point
}
void OnMouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
points.Add(e.Location); // Add points to path
Invalidate(); // Force to repaint
}
void OnMouseUp(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
SaveToBitmap(); // Save the drawn line to bitmap
points.Clear(); // Our drawing is saved, we can clear the list of points
}
private void SaveToBitmap()
{
if (points.Count == 0)
return;
using (Graphics g = Graphics.FromImage(bmp))
g.DrawLines(pen, points.ToArray()); // Just draw current line on bitmap
}
}
结果:
我有一个关于 Graphics 对象的问题。我想像 MS paint 一样画一条连续的线。我不知道如何实现这样的事情。我知道如何从鼠标位置开始一行。我在图片框上执行此操作并添加新点 (e.X, e.Y)。当然,另一条线不能相同,否则将看不到任何线。我无法制作另一个 Point(10, 10) 或类似的东西。因为那样它会始终从同一点创建一条线。
有谁知道如何画连续的直线(带曲线)
是否与mouse_down和mouse_up事件有关?我真的被这个问题困扰了很长时间。如果你们中的任何人有时间向我解释可行的方法,那就太好了!
提前致谢!
大体上:
- 在
MouseDown
上,捕获鼠标并存储当前位置。此位置是您的初始Point
值。 - 在
MouseMove
上,将当前位置添加到您的点列表中。 - 在
MouseUp
上,根据需要完成曲线,停止捕获鼠标。
渲染时,将 Point
值列表转换为数组并将其传递给 Graphics.DrawLines()
方法。作为一种可能的优化,一旦用户完成绘图,就将列表永久转换为数组。或者,使用 Bitmap
实例作为渲染缓存。
请注意,您可以配置用于绘制线条的 Pen
对象以应用特殊效果,如端盖和斜接接头。
要绘制曲线,请改用Graphics.DrawBeziers()
方法。请注意,在这种情况下,鼠标事件期间捕获的点应该是传递给方法的数组中的每隔三个点。每个点之间的两点是每条曲线的控制点。
您可能应该从 DrawLines()
开始,因为它更简单。一旦你让它工作得很好,那么你就可以使用 DrawBeziers()
方法使你的生活复杂化。至少,您必须自动计算用于该方法的默认控制点。最好给用户一个编辑控制点的方法,这样他们就可以自定义曲线了。
我刚刚为您实现了简单的绘画。只需创建一个新项目并将下面的代码复制到 Form1.cs 文件。代码中的注释应该解释它是如何工作的。
public partial class Form1 : Form
{
private Bitmap bmp; // Place to store our drawings
private List<Point> points; // Points of currently drawing line
private Pen pen; // Pen we will use to draw
public Form1()
{
InitializeComponent();
DoubleBuffered = true; // To avoid flickering effect
bmp = new Bitmap(640, 480); // This is our canvas that will store drawn lines
using (Graphics g = Graphics.FromImage(bmp))
g.Clear(Color.White); // Let's make it white, like paper
points = new List<Point>(); // Here we will remember the whole path
pen = new Pen(Color.Black);
MouseDown += OnMouseDown; // Start drawing
MouseMove += OnMouseMove; // Drawing...
MouseUp += OnMouseUp; // Stop drawing
Paint += OnPaint; // Show the drawing
}
void OnPaint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(bmp, 0, 0); // Show what is drawn
if (points.Count > 0)
e.Graphics.DrawLines(pen, points.ToArray()); // Show what is currently being drawn
}
void OnMouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
points.Clear();
points.Add(e.Location); // Remember the first point
}
void OnMouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
points.Add(e.Location); // Add points to path
Invalidate(); // Force to repaint
}
void OnMouseUp(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
SaveToBitmap(); // Save the drawn line to bitmap
points.Clear(); // Our drawing is saved, we can clear the list of points
}
private void SaveToBitmap()
{
if (points.Count == 0)
return;
using (Graphics g = Graphics.FromImage(bmp))
g.DrawLines(pen, points.ToArray()); // Just draw current line on bitmap
}
}
结果: