如何在图片框中每次单击鼠标时绘制一个小点 [英] How to draw a small dot on every click of the mouse in a PictureBox

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

问题描述

我有一个 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().

你可以这样测试:

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

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 像素大小的橙色 Pen
newPoint.DrawingPen = new Pen(Color.Orange, 2);

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

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

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

Clear() 方法用于Dispose() 点的当前列表并创建一个新的空列表:
MyPoints.Clear();

The Clear() method is 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);
    (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();
}

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

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

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

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

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