在单击位置绘制一个新的圆位图,同时保留以前绘制的圆

Drawing a new circle bitmap at the click location while preserving previously drawn circles

我正在尝试使用位图绘制圆圈。

每次点击鼠标,我之前画的圆都会移动到新的位置。

我想要发生的是:每次我点击鼠标,一个新的圆在我点击的位置created/drawn,之前画的所有圆保持不动。

我正在使用以下代码:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace multirectangle
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    }
    Bitmap background;
    Graphics scG;

    Rectangle rectangleObj;

    private Point clickCurrent = Point.Empty;
    private Point clickPrev = Point.Empty;


    private void Form1_Load(object sender, EventArgs e)
    {
        background = new Bitmap(Width, Height);
        rectangleObj = new Rectangle(10, 10, 30, 30);
        scG = Graphics.FromImage(background);
    }

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        clickCurrent = PointToClient(Cursor.Position);
        clickPrev = clickCurrent;
        if (clickPrev == Point.Empty) return;
        rectangleObj.X = clickPrev.X - rectangleObj.Height / 2;// +radius; 
        rectangleObj.Y = clickPrev.Y - rectangleObj.Width / 2;
        Refresh();
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        pe.Graphics.DrawImage(Draw(), 0, 0);

    }
    public Bitmap Draw()
    {
        Graphics scG = Graphics.FromImage(background);
        Pen myPen = new Pen(System.Drawing.Color.Red, 3);
        scG.Clear(SystemColors.Control);
        scG.DrawEllipse(myPen, rectangleObj);
        return background;

    }
}
}

我注意到一些事情。首先,在 Form1_MouseDown() 中,你有这个:

clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;

您甚至在保存之前就覆盖了旧位置 (clickPrev)。如果你想保留这两个位置,你应该把它们放在一个简单的结构中,比如一个列表。当你得到一个新点时,只需 Add() 将它添加到列表中。然后,在您的 Draw() 例程中,遍历列表中的所有元素并将它们全部绘制出来。

如果您只想要两个职位——而且只有两个——只需像这样交换您的陈述:

clickPrev = clickCurrent;
clickCurrent = PointToClient(Cursor.Position);

而且您必须为绘图分配另一个矩形对象,尽管在 Draw() 例程中处理它更有意义。

交换以下语句的位置

clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;

我认为您在初始化 clickCurrent 后将 clickCurrent 分配给 clickPrevious。需要反过来。

你的英语有点混乱。如果我对您的问题的理解正确,那么现在唯一绘制的是点击所在的新圆圈,并且您希望所有旧圆圈也保持不变?在这种情况下,有两种选择:

  1. 绘制前不要清除位图。 scG.Clear(SystemColors.Control); 将清除您刚刚绘制的位图。如果您删除该行并且不清除位图,那么下次您单击时,它将在最后一个位图的顶部绘制新的椭圆。
  2. 如果您每次都想要新鲜的 drawing/bitmap,则需要一份 rectangleObj 的列表。每次单击时,都会将该点添加到 rectangleObj collection。然后在你的 draw 方法中,你将遍历 collection 并绘制所有它们。

请试试这个

Rectangle rectangleObj;
Bitmap background;
Graphics scG;
Pen myPen;

private void Form1_Load(object sender, EventArgs e)
{
    rectangleObj = new Rectangle(10, 10, 30, 30);
    background = new Bitmap(Width, Height);
    scG = Graphics.FromImage(background);
    myPen = new Pen(Color.Red, 3);

    BackgroundImage = background;
}

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    var point = PointToClient(Cursor.Position);

    rectangleObj.X = point.X - rectangleObj.Height / 2;
    rectangleObj.Y = point.Y - rectangleObj.Width / 2;

    scG.DrawEllipse(myPen, rectangleObj);
    Refresh();
}

OnPaintDraw 方法已删除。以及 clickCurrentclickPrev 字段。

当您更改表单大小时(例如,最大化它),Bitmap 和 Graphics 保持不变,因此您会得到这种效果。为避免这种情况,您需要添加事件处理程序

private void Form1_SizeChanged(object sender, EventArgs e)
{
    background = new Bitmap(Width, Height);
    scG = Graphics.FromImage(background);
    BackgroundImage = background;
}

请注意,每次调整表格大小时,之前绘制的所有内容都会被删除。如果这是不可取的,则需要采用不同的方法进行绘图。告诉我,我再举个例子。