如何在WinForms PictureBox中的鼠标的每次单击上绘制小点 [英] How to draw small dot on every click of the mouse in WinForms PictureBox

查看:150
本文介绍了如何在WinForms PictureBox中的鼠标的每次单击上绘制小点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a WinForms program where the user clicks on a PictureBox control.
I want a small red dot (a few pixels across) every time the user clicks.
I also don't want any of the previous dots to go away.

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

I know I will need a generic list of ellipses and rectangles, but am not sure how to execute this. How would I go about doing this?

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

In my program a pictureBox1_Click method handles mouse click events and returns the position of the clicks.
A pictureBox1_Paint method handles the graphics to be drawn on these points.

推荐答案

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

You have to create a container that can reference the Points collection and add one point to the collection each time you click on a paint-able Control.

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

Maybe, you want to also create different kinds of drawing points, based on some conditions or requirements.
Thus, you need to store also these extra properties, not just a point coordinate.
If so, you need a specialized object that can expose these properties when needed.

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

So, here's a custom Class object with some simple properties, that lets you define a Point's Color and Size. For each of its Points collection.
It also implements the IDisposable interface, because we need to create a Pen object for each Point we draw. And a Pen object needs to be disposed (implements IDisposable).

要执行绘图,只需调用 Control.Invalidate() (在示例中为pictureBox1.Invalidate()).这将导致控件无效部分的重新绘制,从而引发 OnPaint() 事件.
每个点(需要重绘)都使用 e.Graphics.DrawEllipse()

To perform the drawing, you just need to call Control.Invalidate() (pictureBox1.Invalidate() in the example). This causes the repainting of the invalidated parts of the control, raising the OnPaint() event.
Each point (that needs to be repainted) is drawn using e.Graphics.DrawEllipse()

您可以通过以下方式进行测试:

You can test it this way:

具有预定义的属性,仅使用鼠标指针坐标即可:

myPoints.Add(new MyPoints.DrawingPoint(e.Location));

myPoints.Add(new MyPoints.DrawingPoint(e.Location));

具有特定属性,需要其他功能时:

尺寸为8x8像素
newPoint.Dot = new Rectangle(e.Location, new Size(8, 8)));

With a size of 8x8 pixels
newPoint.Dot = new Rectangle(e.Location, new Size(8, 8)));

使用2像素大小的橙色钢笔
newPoint.DrawingPen = new Pen(Color.Orange, 2);

With an orange Pen of 2 pixels in size
newPoint.DrawingPen = new Pen(Color.Orange, 2);

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

Add this new Point to the collection
myPoints.DrawingPoints.Add(newPoint);


Clear()方法添加到Main对象,该方法用于Dispose()当前点列表并创建一个新的空List:
MyPoints.Clear();


Adden a Clear() method to the Main object, used to Dispose() the current list of Points and create a new, empty, 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对象集合类容器:

The Point objects collection Class container:

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

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

This is how it can work, changing its properties when required:


这篇关于如何在WinForms PictureBox中的鼠标的每次单击上绘制小点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆