如何在 PictureBox 中每次单击鼠标时绘制一个小点
How to draw a small dot on every click of the mouse in a PictureBox
我有一个 WinForms
程序,用户可以在其中单击 PictureBox
控件。
每次用户点击时我都想要一个小红点(几个像素)。
我也不希望之前的任何点消失。
我知道我需要一个椭圆和矩形的通用列表,但我不确定如何执行它。我该怎么做?
在我的程序中,pictureBox1_Click
方法处理鼠标点击事件和 returns 点击位置。
pictureBox1_Paint
方法处理要在这些点上绘制的图形。
基本上你必须使用GDI+
检查下面的代码:
private void pictureBox1_Click(object sender, EventArgs e)
{
Graphics g = Graphics.FromImage(pictureBox1.Image);
Pen p = new Pen(Color.Red, 3);
var cursorPosition = pictureBox1.PointToClient(Cursor.Position);
g.DrawEllipse(p, cursorPosition.X, cursorPosition.Y, 15, 15);
MyCircles.Add(cursorPosition);
pictureBox1.Refresh();
}
List<Point> MyCircles = new List<Point>();
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
foreach (var item in MyCircles)
{
MessageBox.Show($"One circle was created: X:{item.X}, Y:{item.Y}");
}
}
MyCircles List仅当你想存储圈子以便稍后重新显示带有圈子的图像时,双击是使用它的示例(我的意思是持久性目的,因为圈子不会离开图像直到你关闭你的应用程序)。检查其他 g 方法来绘制线条、矩形或其他任何东西。 (使用 System.Drawing 命名空间)
您必须创建一个可以引用点 collection 的容器,并在每次单击 paint-able 控件时向 collection 添加一个点。
也许,您还想根据某些条件或要求创建不同类型的绘图点。
因此,您还需要存储这些额外的属性,而不仅仅是点坐标。
如果是这样,您需要一个专门的 object 可以在需要时公开这些属性。
因此,这是一个具有一些简单属性的自定义 Class
object,可让您定义点的颜色和大小。对于它的每个点 collection.
它还实现了IDisposable
接口,因为我们需要为每个Point创建一个Pen
object我们画。并且需要处理 Pen
object (implements IDisposable
).
要执行绘图,您只需调用Control.Invalidate()
(示例中为pictureBox1.Invalidate()
)。这会导致重新绘制控件的无效部分,引发 OnPaint()
事件。
每个点(需要重新绘制)使用 e.Graphics.DrawEllipse()
.
绘制
你可以这样测试:
具有预定义属性,仅使用鼠标指针坐标:
myPoints.Add(new MyPoints.DrawingPoint(e.Location));
当需要不同的东西时具有特定的属性:
尺寸为 8x8 像素
newPoint.Dot = new Rectangle(e.Location, new Size(8, 8)));
.
使用 2 像素大小的橙色笔
newPoint.DrawingPen = new Pen(Color.Orange, 2);
将这个新点添加到 collection
myPoints.DrawingPoints.Add(newPoint);
Clear()
方法用于Dispose()
当前点列表并创建一个新的空列表:
MyPoints.Clear();
示例实现:
MyPoints myPoints = new MyPoints();
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
//Use default property values
//myPoints.Add(new MyPoints.DrawingPoint(e.Location));
MyPoints.DrawingPoint newPoint = new MyPoints.DrawingPoint();
newPoint.Dot = new Rectangle(e.Location, new Size(4, 4));
newPoint.DrawingPen = new Pen(Color.Red, 2);
myPoints.DrawingPoints.Add(newPoint);
(sender as Control).Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (MyPoints.DrawingPoint mypoint in myPoints.DrawingPoints) {
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawEllipse(mypoint.DrawingPen, mypoint.Dot);
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
myPoints.Dispose();
}
点objects collectionClass容器:
internal class MyPoints : IDisposable
{
bool IsDisposed = false;
public MyPoints() => DrawingPoints = new List<DrawingPoint>();
public List<DrawingPoint> DrawingPoints { get; set; }
public void Add(DrawingPoint NewPoint)
{
if (NewPoint.Dot.Size.Width > 1 && NewPoint.Dot.Size.Height > 1) {
DrawingPoints.Add(NewPoint);
}
}
public void Clear()
{
this.Dispose();
this.DrawingPoints.Clear();
this.DrawingPoints = new List<DrawingPoint>();
}
public void Remove(Point point)
{
Remove(this.DrawingPoints.Select((p, i) => { if (p.Dot.Contains(point)) return i; return -1; }).First());
}
public void Remove(int Index)
{
if (Index > -1) {
this.DrawingPoints[Index].Delete();
this.DrawingPoints.RemoveAt(Index);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool IsSafeDisposing)
{
if (IsSafeDisposing && (!this.IsDisposed) && (this.DrawingPoints.Count > 0)) {
foreach (DrawingPoint dp in this.DrawingPoints)
if (dp != null) dp.Delete();
}
}
public class DrawingPoint
{
Pen m_Pen = null;
Rectangle m_Dot = Rectangle.Empty;
public DrawingPoint() : this(Point.Empty) { }
public DrawingPoint(Point newPoint)
{
this.m_Pen = new Pen(Color.Red, 1);
this.m_Dot = new Rectangle(newPoint, new Size(2, 2));
}
public Pen DrawingPen { get => this.m_Pen; set => this.m_Pen = value; }
public Rectangle Dot { get => this.m_Dot; set => this.m_Dot = value; }
public void Delete()
{
if (this.m_Pen != null) this.m_Pen.Dispose();
}
}
}
这是它的工作方式,需要时更改其属性:
我想出了一个简单的解决方案来解决我的问题
我制作了一个矩形列表:
List<Rectangle> rects = new List<Rectangle>();
并通过单击添加矩形:
private void pictureBox1_Click(object sender, MouseEventArgs e)
{
rects.Add(new Rectangle(e.Location, new Size(4,4)));
}
并画点:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (var rect in rects)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawEllipse(magenta,rect);
}
}
并添加了清除图纸的方法 rects.Clear()
我有一个 WinForms
程序,用户可以在其中单击 PictureBox
控件。
每次用户点击时我都想要一个小红点(几个像素)。
我也不希望之前的任何点消失。
我知道我需要一个椭圆和矩形的通用列表,但我不确定如何执行它。我该怎么做?
在我的程序中,pictureBox1_Click
方法处理鼠标点击事件和 returns 点击位置。
pictureBox1_Paint
方法处理要在这些点上绘制的图形。
基本上你必须使用GDI+
检查下面的代码:
private void pictureBox1_Click(object sender, EventArgs e)
{
Graphics g = Graphics.FromImage(pictureBox1.Image);
Pen p = new Pen(Color.Red, 3);
var cursorPosition = pictureBox1.PointToClient(Cursor.Position);
g.DrawEllipse(p, cursorPosition.X, cursorPosition.Y, 15, 15);
MyCircles.Add(cursorPosition);
pictureBox1.Refresh();
}
List<Point> MyCircles = new List<Point>();
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
foreach (var item in MyCircles)
{
MessageBox.Show($"One circle was created: X:{item.X}, Y:{item.Y}");
}
}
MyCircles List仅当你想存储圈子以便稍后重新显示带有圈子的图像时,双击是使用它的示例(我的意思是持久性目的,因为圈子不会离开图像直到你关闭你的应用程序)。检查其他 g 方法来绘制线条、矩形或其他任何东西。 (使用 System.Drawing 命名空间)
您必须创建一个可以引用点 collection 的容器,并在每次单击 paint-able 控件时向 collection 添加一个点。
也许,您还想根据某些条件或要求创建不同类型的绘图点。
因此,您还需要存储这些额外的属性,而不仅仅是点坐标。
如果是这样,您需要一个专门的 object 可以在需要时公开这些属性。
因此,这是一个具有一些简单属性的自定义 Class
object,可让您定义点的颜色和大小。对于它的每个点 collection.
它还实现了IDisposable
接口,因为我们需要为每个Point创建一个Pen
object我们画。并且需要处理 Pen
object (implements IDisposable
).
要执行绘图,您只需调用Control.Invalidate()
(示例中为pictureBox1.Invalidate()
)。这会导致重新绘制控件的无效部分,引发 OnPaint()
事件。
每个点(需要重新绘制)使用 e.Graphics.DrawEllipse()
.
你可以这样测试:
具有预定义属性,仅使用鼠标指针坐标:
myPoints.Add(new MyPoints.DrawingPoint(e.Location));
当需要不同的东西时具有特定的属性:
尺寸为 8x8 像素
newPoint.Dot = new Rectangle(e.Location, new Size(8, 8)));
.
使用 2 像素大小的橙色笔
newPoint.DrawingPen = new Pen(Color.Orange, 2);
将这个新点添加到 collection
myPoints.DrawingPoints.Add(newPoint);
Clear()
方法用于Dispose()
当前点列表并创建一个新的空列表:
MyPoints.Clear();
示例实现:
MyPoints myPoints = new MyPoints();
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
//Use default property values
//myPoints.Add(new MyPoints.DrawingPoint(e.Location));
MyPoints.DrawingPoint newPoint = new MyPoints.DrawingPoint();
newPoint.Dot = new Rectangle(e.Location, new Size(4, 4));
newPoint.DrawingPen = new Pen(Color.Red, 2);
myPoints.DrawingPoints.Add(newPoint);
(sender as Control).Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (MyPoints.DrawingPoint mypoint in myPoints.DrawingPoints) {
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawEllipse(mypoint.DrawingPen, mypoint.Dot);
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
myPoints.Dispose();
}
点objects collectionClass容器:
internal class MyPoints : IDisposable
{
bool IsDisposed = false;
public MyPoints() => DrawingPoints = new List<DrawingPoint>();
public List<DrawingPoint> DrawingPoints { get; set; }
public void Add(DrawingPoint NewPoint)
{
if (NewPoint.Dot.Size.Width > 1 && NewPoint.Dot.Size.Height > 1) {
DrawingPoints.Add(NewPoint);
}
}
public void Clear()
{
this.Dispose();
this.DrawingPoints.Clear();
this.DrawingPoints = new List<DrawingPoint>();
}
public void Remove(Point point)
{
Remove(this.DrawingPoints.Select((p, i) => { if (p.Dot.Contains(point)) return i; return -1; }).First());
}
public void Remove(int Index)
{
if (Index > -1) {
this.DrawingPoints[Index].Delete();
this.DrawingPoints.RemoveAt(Index);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool IsSafeDisposing)
{
if (IsSafeDisposing && (!this.IsDisposed) && (this.DrawingPoints.Count > 0)) {
foreach (DrawingPoint dp in this.DrawingPoints)
if (dp != null) dp.Delete();
}
}
public class DrawingPoint
{
Pen m_Pen = null;
Rectangle m_Dot = Rectangle.Empty;
public DrawingPoint() : this(Point.Empty) { }
public DrawingPoint(Point newPoint)
{
this.m_Pen = new Pen(Color.Red, 1);
this.m_Dot = new Rectangle(newPoint, new Size(2, 2));
}
public Pen DrawingPen { get => this.m_Pen; set => this.m_Pen = value; }
public Rectangle Dot { get => this.m_Dot; set => this.m_Dot = value; }
public void Delete()
{
if (this.m_Pen != null) this.m_Pen.Dispose();
}
}
}
这是它的工作方式,需要时更改其属性:
我想出了一个简单的解决方案来解决我的问题 我制作了一个矩形列表:
List<Rectangle> rects = new List<Rectangle>();
并通过单击添加矩形:
private void pictureBox1_Click(object sender, MouseEventArgs e)
{
rects.Add(new Rectangle(e.Location, new Size(4,4)));
}
并画点:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (var rect in rects)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawEllipse(magenta,rect);
}
}
并添加了清除图纸的方法 rects.Clear()