面板到图像(DrawToBtimap不起作用)

时间:2019-06-26 11:38:25

标签: c# winforms

我正在尝试制作类似于Paint的应用程序。

一切正常,但将图像保存到文件时出现问题。 保存功能正常,文件保存在所选位置,但是在绘制内容时为空。

仅当我更改背景颜色时,该功能才有效,然后图像将以此颜色保存。

当我“画”类似的东西

image

保存的图像如下所示

image

代码:

private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
    int width = pnl_Draw.Width;
    int height = pnl_Draw.Height;

    Bitmap bm = new Bitmap(width, height);


    SaveFileDialog sf = new SaveFileDialog();
    sf.Filter = "Bitmap Image (.bmp)|*.bmp|Gif Image (.gif)|*.gif|JPEG Image (.jpeg)|*.jpeg|Png Image (.png)|*.png|Tiff Image (.tiff)|*.tiff|Wmf Image (.wmf)|*.wmf";
    sf.ShowDialog();
    var path = sf.FileName;

    pnl_Draw.DrawToBitmap(bm, new Rectangle(0, 0, width, height));
    bm.Save(path, ImageFormat.Jpeg);

}

绘图:

  private void pnl_Draw_MouseMove(object sender, MouseEventArgs e)
    {
        if(startPaint)
        {
            //Setting the Pen BackColor and line Width
            Pen p = new Pen(btn_PenColor.BackColor,float.Parse(cmb_PenSize.Text));
            //Drawing the line.
            g.DrawLine(p, new Point(initX ?? e.X, initY ?? e.Y), new Point(e.X, e.Y));
            initX = e.X;
            initY = e.Y;
        }
    }

1 个答案:

答案 0 :(得分:-1)

当您在其上绘制线条时,“ g”(System.Drawing.Graphics?)对象从何而来?我也看不到您在哪里填充背景色,但我怀疑您的图形被丢弃/覆盖了-但鉴于此处可见的代码很少,因此很难分辨。

我只是建议过去对我有用的: 使用位图对象将线条等绘制到其中,而不是直接在面板中绘制。当您要保存它时,只需保存位图。 要使图形在面板上可见,请在制作新的线描之后在面板上调用Invalidate(...),并将线描周围的边界矩形作为更新矩形传递给Invalidate。 在面板的OnPaint处理程序中,然后确保仅绘制新的部分,例如我提到的那个矩形。这将作为OnPaint调用的剪辑范围传递。如果仅在OnPaint处理程序中绘制整个图像的更改部分,则它比将整个位图始终绘制到面板上的速度要快得多。 为此,您需要从绘制的位图创建图形对象,并在整个绘制会话中保持位图和图形对象的活动(即,不要通过在某处没有引用它们而使垃圾收集起来)< / p>

大概是这样的:

// assuming you're all doing this directly in your main form, as a simple experimental app:

// Somewhere in your form class:
Bitmap drawingBitmap;
Graphics gfx;


// in your form class' constructor, AFTER the InitializeComponent() call, so the sizes are known:
// using a pixelformat which usually yields good speed vs. non-premultiplied ones
drawingBitmap = new Bitmap( pnl.Width, pnl.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb );
gfx = Graphics.FromImage( drawingBitmap );



private void pnl_Draw_MouseMove(object sender, MouseEventArgs e)
{
    if(startPaint)
    {
        //Setting the Pen BackColor and line Width
        Pen p = new Pen(btn_PenColor.BackColor,float.Parse(cmb_PenSize.Text));
        //Drawing the line.
        var p1 = new Point(initX ?? e.X, initY ?? e.Y);
        var p2 = new Point(e.X, e.Y);
        gfx.DrawLine( p, p1, p2 ); // !!! NOTE: gfx instance variable is used
        initX = e.X;
        initY = e.Y;

        // makes the panel's Paint handler being called soon - with a clip rectangle just covering your new little drawing stroke, not more.
        pnl.Invalidate( new Rectangle( p1.X, p1.Y, 1+p2.X-p1.X, 1+p2.Y-p1.Y ));
    }
}

private void pnl_Paint(object sender, PaintEventArgs e)
{
    var g = e.Graphics;
    // use the clip bounds of the Graphics object to draw only the relevant area, not always everything.
    var sourceBounds = new RectangleF( g.ClipRectangle.X, g.ClipRectangle.Y, g.ClipRectangle.Width, g.ClipRectangle.Height );

    // The bitmap and drawing panel are assumed to have the same size, to make things easier for this example.
    // Actually you might want have a drawing bitmap of a totally unrelated size, and need to apply scaling to a setting changeable by the user.
    g.DrawImage( drawingBitmap, g.ClipRectangle.X, g.ClipRectangle.Y, sourceBounds );
}

关于这点,尽管文章很陈旧。但是自那时以来,GDI +并没有发生太大变化,因为它是Win32绘图内容的包装。 https://www.codeproject.com/Articles/1355/Professional-C-Graphics-with-GDI

注意:我现在没有时间检查并且不记得是您是否同时被允许

  • 具有位图的“开放”图形对象并绘制到位图中
  • 将相同的位图绘制到其他内容(如面板)上
  • 将位图保存到文件

您必须检查一下,并相应地管理图形对象的存在以及其爪在绘图位图上。