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

C# 在单击位置绘制新的圆位图,同时保留以前绘制的圆,c#,bitmap,system.drawing,C#,Bitmap,System.drawing,我正在尝试使用位图绘制圆 每次单击鼠标时,我先前绘制的圆都会移动到新位置 我想做的是:每次单击鼠标时,都会在单击的位置创建/绘制一个新的圆,并且所有以前绘制的圆都不会移动 我正在使用以下代码: using System; using System.Drawing; using System.Windows.Forms; namespace multirectangle { public partial class Form1 : Form { public Form1() {

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

每次单击鼠标时,我先前绘制的圆都会移动到新位置

我想做的是:每次单击鼠标时,都会在单击的位置创建/绘制一个新的圆,并且所有以前绘制的圆都不会移动

我正在使用以下代码:

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;

    }
}
}

我注意到一些事情。首先,在
表单1\u MouseDown()
中,您有:

clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;
在保存之前,您正在覆盖旧位置(
单击prev
)。如果你想保留这两个位置,你应该把它们放在一个简单的结构中,比如一个列表。当您获得一个新点时,只需将它添加到列表中即可。然后,在
Draw()
例程中,循环列表中的所有元素并全部绘制

如果您只需要两个位置,而且只有两个位置,只需像这样交换您的语句:

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

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

我注意到一些事情。首先,在
表单1\u MouseDown()
中,您有:

clickCurrent = PointToClient(Cursor.Position);
clickPrev = clickCurrent;
在保存之前,您正在覆盖旧位置(
单击prev
)。如果你想保留这两个位置,你应该把它们放在一个简单的结构中,比如一个列表。当您获得一个新点时,只需将它添加到列表中即可。然后,在
Draw()
例程中,循环列表中的所有元素并全部绘制

如果您只需要两个位置,而且只有两个位置,只需像这样交换您的语句:

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

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

交换以下语句的位置

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

我认为您在初始化
clickCurrent
后将
clickCurrent
分配给
clickPrevious
。它需要另一种方式。

交换以下语句的位置

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

我认为您在初始化
clickCurrent
后将
clickCurrent
分配给
clickPrevious
。你的英语有点让人困惑。如果我对你的问题理解正确的话,现在唯一被画出来的就是点击所在的新圆圈,你想让所有的旧圆圈都继续存在吗?在这种情况下,有两种选择:

  • 绘制前不要清除位图<代码>scG.Clear(SystemColor.Control)将清除刚才绘制的位图。如果删除该行而不清除位图,则下次单击时,它将在上一个位图的正上方绘制新的椭圆
  • 如果您每次都想要一个新的绘图/位图,您需要一个
    矩形对象的列表。每次单击时,都会将该点添加到
    rectangleObj
    集合中。然后在draw方法中,您将遍历集合并绘制所有集合

  • 你的英语有点混乱。如果我对你的问题理解正确的话,现在唯一被画出来的就是点击所在的新圆圈,你想让所有的旧圆圈都继续存在吗?在这种情况下,有两种选择:

  • 绘制前不要清除位图<代码>scG.Clear(SystemColor.Control)将清除刚才绘制的位图。如果删除该行而不清除位图,则下次单击时,它将在上一个位图的正上方绘制新的椭圆
  • 如果您每次都想要一个新的绘图/位图,您需要一个
    矩形对象的列表。每次单击时,都会将该点添加到
    rectangleObj
    集合中。然后在draw方法中,您将遍历集合并绘制所有集合
  • 请试试这个

    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();
    }
    
    OnPaint
    Draw
    方法已删除。以及
    clickCurrent
    clickPrev
    字段

    当您更改表单大小(例如,最大化表单大小)时,位图和图形保持不变,因此您可以获得此效果。为了避免这种情况,您需要添加事件处理程序

    private void Form1_SizeChanged(object sender, EventArgs e)
    {
        background = new Bitmap(Width, Height);
        scG = Graphics.FromImage(background);
        BackgroundImage = background;
    }
    
    请注意,每次调整窗体大小时,以前绘制的所有内容都将被删除。如果这是不需要的,则需要另一种绘制方法。让我知道,我再举一个例子。

    请试试这个

    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();
    }
    
    OnPaint
    Draw
    方法已删除。以及
    clickCurrent
    clickPrev
    字段

    当您更改表单大小(例如,最大化表单大小)时,位图和图形保持不变,因此您可以获得此效果。为了避免这种情况,您需要添加事件处理程序

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

    请注意,每次调整窗体大小时,以前绘制的所有内容都将被删除。如果这是不需要的,则需要另一种绘制方法。让我知道,我再举一个例子。

    记住,程序不知道你上一帧画了什么。你需要保留一个最有可能的位置列表,然后在每一帧绘制它们。这
    scG.Clear
    始终会清除位图。删除它并报告。还要注意,这有点复杂,说得委婉一点。记住,程序不知道你上一帧画了什么。你需要保留一个最有可能的位置列表,然后在每一帧绘制它们。这
    scG.Clear
    始终会清除位图。删除它并报告。还请注意,这有点复杂,说得委婉一点谢谢你回答这个问题,你是对的我的英语不是最好的而且你得到了我需要的方法一不能满足我的需要,方法2更现实,我也考虑过。但因为我对c#不熟悉,我不知道应用它的编码过程。例如,我想列出矩形0bj,允许我画100个圆。。我该怎么做?在你们班上,你们想要一个