C# Winforms中的绘图

C# Winforms中的绘图,c#,winforms,drawing,C#,Winforms,Drawing,我已经写了这段代码,但是它不起作用。这不仅不起作用,而且我尝试过的绘画方法都不起作用。我花了一两个多小时试图解决这个问题,但没有成功。我试过一些简单的程序,它只显示一小行,但不管我做什么,它都不起作用 我做错了什么,或者是什么导致了这一切 private void pictureBox1_MouseDown(object sender, MouseEventArgs m,

我已经写了这段代码,但是它不起作用。这不仅不起作用,而且我尝试过的绘画方法都不起作用。我花了一两个多小时试图解决这个问题,但没有成功。我试过一些简单的程序,它只显示一小行,但不管我做什么,它都不起作用

我做错了什么,或者是什么导致了这一切

private void pictureBox1_MouseDown(object sender, 
                                   MouseEventArgs m, 
                                   EventArgs e, 
                                   PaintEventArgs q)
{
    if (m.Button == System.Windows.Forms.MouseButtons.Left)
    {
        Point currpoint = System.Windows.Forms.Cursor.Position;

        Point origin = new Point(0, 0);

        decimal sizee = nud.Value;

        int size = Convert.ToInt32(sizee);

        Random randonGen = new Random();

        Color randomColor = Color.FromArgb(randonGen.Next(255),
                                           randonGen.Next(255),
                                           randonGen.Next(255));

        Pen selPen = new Pen(randomColor, size);

        Graphics g = Graphics.FromImage(pictureBox1.Image);

        g.DrawLine(selPen, 3, 3, 133, 133);
    }
}
尝试添加一个

pictureBox1.Invalidate();
呼叫。

尝试添加

pictureBox1.Invalidate();

呼叫。

这不是绘制图片框的正确方法:

private void pictureBox1_MouseDown(object sender, 
                                   MouseEventArgs m, 
                                   EventArgs e, 
                                   PaintEventArgs q)
{
    if (m.Button == System.Windows.Forms.MouseButtons.Left)
    {
        Point currpoint = System.Windows.Forms.Cursor.Position;

        Point origin = new Point(0, 0);

        decimal sizee = nud.Value;

        int size = Convert.ToInt32(sizee);

        Random randonGen = new Random();

        Color randomColor = Color.FromArgb(randonGen.Next(255),
                                           randonGen.Next(255),
                                           randonGen.Next(255));

        Pen selPen = new Pen(randomColor, size);

        using(Graphics g = pictureBox1.CreateGraphics()) // Use the CreateGraphics method to create a graphic and draw on the picture box. Use using in order to free the graphics resources.
        {
             g.DrawLine(selPen, 3, 3, 133, 133);
        }
    }
}

顺便说一句,此方法将创建一个临时映像,当控件无效时,该映像将被重置。对于更持久的绘图,您需要收听图片框的绘制事件并在那里绘制图形。

这不是绘制图片框的正确方法:

private void pictureBox1_MouseDown(object sender, 
                                   MouseEventArgs m, 
                                   EventArgs e, 
                                   PaintEventArgs q)
{
    if (m.Button == System.Windows.Forms.MouseButtons.Left)
    {
        Point currpoint = System.Windows.Forms.Cursor.Position;

        Point origin = new Point(0, 0);

        decimal sizee = nud.Value;

        int size = Convert.ToInt32(sizee);

        Random randonGen = new Random();

        Color randomColor = Color.FromArgb(randonGen.Next(255),
                                           randonGen.Next(255),
                                           randonGen.Next(255));

        Pen selPen = new Pen(randomColor, size);

        using(Graphics g = pictureBox1.CreateGraphics()) // Use the CreateGraphics method to create a graphic and draw on the picture box. Use using in order to free the graphics resources.
        {
             g.DrawLine(selPen, 3, 3, 133, 133);
        }
    }
}

顺便说一句,此方法将创建一个临时映像,当控件无效时,该映像将被重置。要获得更持久的绘图,您需要收听图片框的绘制事件,并在其中绘制图形。

您必须首先从图像绘制图形。然后将其附加到
pictureBox1

Bitmap canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
Graphics g = Graphics.FromImage(canvas);

Point currpoint = System.Windows.Forms.Cursor.Position;

Point origin = new Point(0, 0);

decimal sizee = nud.Value;

int size = Convert.ToInt32(sizee);

Random randonGen = new Random();

Color randomColor = Color.FromArgb(randonGen.Next(255),
                                   randonGen.Next(255),
                                   randonGen.Next(255));

Pen selPen = new Pen(randomColor, size);

g.DrawLine(selPen, 3, 3, 133, 133);
pictureBox1.image = canvas;

你们必须先从图像中画出来。然后将其附加到
pictureBox1

Bitmap canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
Graphics g = Graphics.FromImage(canvas);

Point currpoint = System.Windows.Forms.Cursor.Position;

Point origin = new Point(0, 0);

decimal sizee = nud.Value;

int size = Convert.ToInt32(sizee);

Random randonGen = new Random();

Color randomColor = Color.FromArgb(randonGen.Next(255),
                                   randonGen.Next(255),
                                   randonGen.Next(255));

Pen selPen = new Pen(randomColor, size);

g.DrawLine(selPen, 3, 3, 133, 133);
pictureBox1.image = canvas;

这是一个老问题,如果其他人也有类似的问题。见下文。首先让我们检查一下Ops代码

(1) 请参见代码:第一个建议的更改是保持画笔的格式简单,直到我们更好地了解画笔在绘制图形时的实际工作方式。看看Op的线条,我们从图像中创建图形,这是一个非常好的示例,说明了如何使用位图的图形上下文直接将(“这意味着写入”)绘制到提供的位图。接下来,Op提供了一个图形绘制线方法的优秀示例,该方法可以将定义的线绘制到提供的位图

(2) 由于缺少详细信息,我们必须对Op提供的位图及其绘制位图线的方法进行以下假设。假设此图片中已经存在一个图像bx1;如果未设置图像,我们从图像中获得的图形将来自空图像,或者每个像素将为黑色,就像脚注一样:

(a) 画笔的颜色是否是现有位图的唯一颜色,并且颜色的alpha分量是否足够高,以便在绘制画笔时实际看到合成颜色(如果有疑问,请使用唯一的纯色或至少将alpha通道设置为255)

(b) Op想要绘制的这条线从3开始,3到133,这是位图左侧右侧的3个像素,其中这条线的高度为133,因此为了演示,笔的线大小被更改为宽度=3

(c) 最后要考虑的是,图片box1.Size是否足以让我们看到这条绘制的线?线条的几何图形形成了一个类似于矩形F(3,3,3,133)结构的矩形,因此如果pictureBox1边界矩形与派生线条的矩形相交,那么该相交的区域就是可以绘制线条并将其视为可见的区域

在从图形绘制到pictureBox1图像之前,我们必须首先将pictureBox1图像数据转换回可用的图像类型,例如位图。原因是图片框仅存储阵列格式的像素数据,GDI/GDI+无法在不转换为图像类型(如bitamp、jpeg、png等)的情况下直接使用

如果通过自定义用户控件和正确处理PaintEventArgsOnPaint实现和/或使用相关图形屏幕缓冲区上下文场景来处理自己的绘制,则可以避免这种混乱的转换

对于那些只想知道缺少什么的人:

    private void button1_Click(Object sender, EventArgs e)
    {
        Pen selPen = new Pen(Color.Red, 2);  //  The Op uses random color which is not good idea for testing so we'll choose a solid color not on the existing bitmap and we'll confine our Pen's line size to 2 until we know what we're doing.

        //  Unfortionately the picture box "image" once loaded is not directly usable afterwords.

        //  We need tp recreate the pictureBox1 image to a usable form, being the "newBmp", and for efficiency the bitmap type is chosen
        Bitmap newBmp = new Bitmap(pictureBox1.Width, pictureBox1.Height, PixelFormat.Format32bppArgb); // Tip: Using System.Drawing.Imaging for pixel format which uses same pixel format as screen for speed

        // We create the graphics from our new and empty bitmap container
        Graphics g = Graphics.FromImage(newBmp);

        // Next we draw the pictureBox1 data array to our equivelent sized bitmap container
        g.DrawImage(pictureBox1.Image, 0, 0);

        g.DrawLine(selPen, 3, 3, 3, 133);  // Format: (pen, x1, y1, x2, y2)
        pictureBox1.Image = newBmp;

        //  Don't forget to dispose of no longer needed resources
        g.Dispose();
        selPen.Dispose();
        newBmp.Dispose(); // or save newBmp to file before dispose ie. newBmp.Save("yourfilepath", ImageFormat.Jpeg) or in whatever image type you disire;
    }
到目前为止,Op的代码只在位图的表面画了一条线,如果我们要“看到”这一变化,我们必须将位图保存到文件中,以便以后在图像查看器中查看,或者我们必须将更新后的位图绘制到显示监视器屏幕上

有几种方法可用于绘制显示器屏幕。可以使用的最常见的图形上下文是Control.CreateGraghics(PaintEventArgs)中的图形到屏幕方法和/或使用图形屏幕缓冲区,有时称为并用作手动双缓冲图形上下文,其中所有内容均通过图形中的DrawImage方法实现

在本例中,最简单的解决方案基于Op自己的代码,就是使用pictureBox1控件显示这个新更新的位图。我们只需使用最新更新的位图更新控件的图像,当然,一旦第一次转换为使用图形图像,如上面的代码描述所示


快乐编码

这是一个老问题,如果其他人也有类似的问题。见下文。首先让我们检查一下Ops代码

(1) 请参见代码:第一个建议的更改是保持画笔的格式简单,直到我们更好地了解画笔在绘制图形时的实际工作方式。看看Op的线条,我们从图像中创建图形,这是一个非常好的示例,说明了如何使用位图的图形上下文直接将(“这意味着写入”)绘制到提供的位图。接下来,Op提供了一个图形绘制线方法的优秀示例,该方法可以将定义的线绘制到提供的位图

(2) 由于缺少详细信息,我们必须对Op提供的位图及其绘制位图线的方法进行以下假设。假设此图片中已经存在一个图像bx1;如果没有设置图像,我们从图像中获得的图形将来自一个空图像,或者每个像素都将是黑色的,就像一个空图像一样