C# 在鼠标移动时绘制MS Paint用户定义的矩形

C# 在鼠标移动时绘制MS Paint用户定义的矩形,c#,drawing,C#,Drawing,我现在正在用C#在面板上绘制一些形状。我在更新当前图形时遇到问题。换句话说,我不知道如何创建一个当前阶段(我将在其中绘制当前,比方说矩形)并在面板上绘制它。我可以在面板事件的鼠标上画一个矩形。但是,在面板上按下鼠标后,如何在鼠标移动事件上显示当前矩形???我不想使用使其无效。因为它会清除以前制作的所有面板图形。请帮助我在移动鼠标时显示当前的矩形形状,并仅在释放鼠标后在面板上绘制它 Pen p_white = new Pen(new SolidBrush(Color.White), pen_thi

我现在正在用C#在面板上绘制一些形状。我在更新当前图形时遇到问题。换句话说,我不知道如何创建一个当前阶段(我将在其中绘制当前,比方说矩形)并在面板上绘制它。我可以在面板事件的
鼠标上画一个矩形。但是,在面板上按下鼠标后,如何在
鼠标移动
事件上显示当前矩形???我不想使用
使其无效
。因为它会清除以前制作的所有面板图形。请帮助我在移动鼠标时显示当前的矩形形状,并仅在释放鼠标后在面板上绘制它

Pen p_white = new Pen(new SolidBrush(Color.White), pen_thickness);
int w1 = Math.Abs(starx - curx); int h1 = Math.Abs(stary - cury);
Rectangle rec_new = new Rectangle(starx, stary - h1, w1, h1);
gpath.Reset();
gpath.AddRectangle(rec_new);// code that adds Rectangle in MOUSE_MOVE EVENT

g.DrawPath(p, gpath); 
// Drawing the rectangle on Mouse Release Event. g was already binded to Panel.CreateGraphics 

可以使用Invalidate()调用绘制方法

你必须把你的画全部移到那里!所以这条线

g.DrawPath(p, gpath);
进入绘画活动,如下所示:

e.Graphics.DrawPath(p, gpath);
因为您正在构建一个GraphicsPath,所以这是一个小小的更改。如果像创建更多图形一样构建图形,则必须在那里绘制所有图形

不能像在纸上那样在面板上重复绘制来构建图形;您必须以某种方式存储绘制动作。这听起来很乏味,但在这里你真的只需要移动一行

并且:随着您的进步,它将为您提供无限撤销、缩放等机会。

请参阅以下说明:

Windows窗体控件不支持真正的透明度。这个 透明Windows窗体控件的背景由其 家长

不幸的是,这意味着我们不能用简单的方法做到这一点——将某种透明图像控件置于另一个控件之上。WinForms不能做到这一点

我使用的一种方法是在“前景”缓冲区内进行所有临时绘制(选择、未完成的绘制等),并根据需要使用背景图像控件的
Paint
事件绘制临时对象

给定包含图像的
PaintBox
控件,可以根据需要使用
Paint
事件绘制前景缓冲区,并提供完全透明选项

public partial class Form1 : Form
{
    public Bitmap Foreground;

    public Form1()
    {
        InitializeComponent();

        // Create foreground buffer same size as picture box
        Foreground = new Bitmap(pictureBox1.Width, pictureBox1.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

        // Draw a blue ellipse in the foreground buffer for something to see
        using (var g = Graphics.FromImage(Foreground))
        {
            g.Clear(Color.Transparent);
            g.DrawEllipse(Pens.Blue, 10, 10, 300, 100);
        }
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawImage(Foreground, 0, 0);
    }
}
假设你的图片框里有东西,这会在上面画一个蓝色椭圆

每当您想要更改覆盖的前景图像时,都需要确保重新绘制
PaintBox
控件。使用
Invalidate
方法告诉Windows控件需要重新绘制

还有一些代码:

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            e.SuppressKeyPress = true;
            e.Handled = true;

            // draw foreground to background
            using (var g = Graphics.FromImage(pictureBox1.Image))
                g.DrawImage(Foreground, 0, 0);

            // clear foreground
            using (var g = Graphics.FromImage(Foreground))
                g.Clear(Color.Transparent);
        }
        else if (e.KeyCode == Keys.Space)
        {
            e.SuppressKeyPress = true;
            e.Handled = true;

            // a random number source - probably better at form level
            var rnd = new Random();

            // draw a new random ellipse
            using (var g = Graphics.FromImage(Foreground))
            {
                g.Clear(Color.Transparent);
                g.DrawEllipse(Pens.Red, 0, 0, 30 + rnd.Next(500), 30 + rnd.Next(500));
            }

            // tell Windows to redraw the paintBox to show new foreground image
            pictureBox1.Invalidate();
        }
    }
Enter
将前景缓冲区提交到
PaintBox
中的图像,按
Space
在前景缓冲区中生成一个随机的新红色椭圆


同样的基本技术可以用于各种各样的事情,比如将图像粘贴到特定位置(粘贴到前景缓冲区中并在其中移动,然后在完成后将前景复制到背景之上)、显示选择对象等。

你能把问题说得更清楚吗,,,,你想在哪里显示你的绘图,你想在哪里绘制..我想在面板上绘制我的矩形,像MS Paint一样,我在鼠标向下移动事件中获得起点,然后当我移动鼠标时,我的矩形会像MS Paint一样自动更改其大小,然后只有在鼠标释放后才绘制(保存)。谢谢,这很有效,但是另一个问题出现了,我画的矩形缩小了,并且改变了它的坐标。为什么?我知道当a()失效时就会发生这种情况;被称为,但不是。失效只是使油漆发生。因此,路径中的坐标现在指的是不同的东西。如果没有MouseDown、-Up、-Move和Paint的代码,我们不知道为什么……但我可以猜测:一些事件可能涉及到面板,其他事件涉及到表单,是吗?确保所有参考面板,使其坐标表示相同!每个控件都有一个绘画、鼠标等事件!形式也是如此。(这是一个控件)不,现在我不在
面板上画画,我在PictureBox上画画,我还有与我的PictureBox事件相关的鼠标按下、鼠标移动、鼠标向上。我正确地绘制了前景图像,从鼠标的下点到鼠标的当前点,移动它可以完美地绘制矩形,向上缩放,向下缩放。但在我释放鼠标后,鼠标移动事件发生了。因此,我的矩形向下缩放并向上移动,从我释放鼠标的点即矩形端点向左移动。这个问题是否由背景图像引起??我将默认的背景作为白纸图片,并将背景和图片的大小设置为相同的谢谢,这是可行的,但出现了另一个问题,我绘制的矩形缩小,并更改其坐标。为什么?我知道当a()失效时就会发生这种情况;被称为此
pictureBox1\u Paint
,此
Form1\u KeyDown
混合了它所指的控件,因此坐标将表示不同的内容;要么让所有事情发生在小组的事件中,要么纠正小组的提议@user3505681如果正在绘制的图像以任何方式进行变换(缩放、转换、缩放等),则需要在绘制代码中执行相同的变换。我使用一个PictureBox来保存图像,无需缩放或其他操作,在一个面板内处理所需的滚动。