如何在WinForms PictureBox中的鼠标的每次单击上绘制小点

时间:2018-10-01 21:59:45

标签: c# winforms paint

我有一个WinForms程序,用户单击PictureBox控件。
每次用户点击时,我都希望有一个小小的红点(跨越几个像素)。
我也不希望前面的点消失。

我知道我将需要一个椭圆和矩形的通用列表,但是不确定如何执行此操作。我该怎么做呢?

在我的程序中,一个pictureBox1_Click方法处理鼠标单击事件并返回单击位置。
pictureBox1_Paint方法处理在这些点上绘制的图形。

3 个答案:

答案 0 :(得分:1)

基本上,您必须使用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列表”才是,而doubleclick是使用它的示例(我指的是持久性,因为直到关闭您的圆圈才会离开图像您的应用)。检查其他 g 方法以绘制线条,矩形或其他形状。 (使用System.Drawing命名空间)

答案 1 :(得分:1)

您必须创建一个容器,该容器可以引用Points集合,并在每次单击可绘制控件时向其中添加一个点。

也许,您还想根据某些条件或要求创建不同种类的工程图点
因此,您还需要存储这些额外的属性,而不仅仅是点坐标。
如果是这样,则需要一个专门的对象,该对象可以在需要时公开这些属性。

因此,这是一个带有一些简单属性的自定义Class对象,可用于定义点的颜色和大小。对于其每个Points集合。
它还实现了 IDisposable 界面,因为我们需要为绘制的每个Point创建一个 Pen 对象。并且需要处置 Pen 对象(实现 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);

将此新Point添加到集合中
myPoints.DrawingPoints.Add(newPoint);

编辑:
Clear()方法添加到Main对象,用于Dispose()的当前点列表并创建一个新的空List:
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);
    ((Control)sender).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();
}

Point对象集合类容器:

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();
        }
    }
}

这是它的工作方式,在需要时更改其属性:

DottedColors1

答案 2 :(得分:0)

我想出了一个简单的解决方案 我列出了一个矩形列表:

        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()清除图形的方法