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

时间:2014-04-07 07:30:09

标签: c# drawing

我现在正在使用C#在PANEL上绘制一些形状。我有更新当前图形的问题。换句话说,我不知道如何创建一个当前阶段(我将绘制当前阶段,让我们说矩形)并在Panel上绘制它。我可以在Panel的Mouse_down事件上绘制一个矩形。但是如何在面板上按下鼠标后,在Mouse_move事件上显示当前的矩形?我不想使用Invalidate。因为它清除了之前制作的所有面板图。帮助我显示当MOUSE被移动时当前的矩形形状,并且仅在鼠标释放后在面板上绘制它。

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 

2 个答案:

答案 0 :(得分:0)

使用Invalidate()来调用Paint方法。

你必须在那里移动全部你的画作!所以这一行

g.DrawPath(p, gpath);

像这样进入Paint事件:

e.Graphics.DrawPath(p, gpath);

由于您正在构建GraphicsPath,因此这是一个小改动。如果你像创建更多的GraphicsPath一样构建你的绘图,那么它们都必须在那里绘制。

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

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

答案 1 :(得分:0)

请参阅MSDN中的此说明:

  

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会在前台缓冲区中生成一个随机的新红色椭圆。

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