我正在尝试制作类似于Paint的应用程序。
一切正常,但将图像保存到文件时出现问题。 保存功能正常,文件保存在所选位置,但是在绘制内容时为空。
仅当我更改背景颜色时,该功能才有效,然后图像将以此颜色保存。
当我“画”类似的东西
保存的图像如下所示
代码:
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;
}
}
答案 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
注意:我现在没有时间检查并且不记得是您是否同时被允许
您必须检查一下,并相应地管理图形对象的存在以及其爪在绘图位图上。