C# 如何保存Winforms面板';将图形内容添加到文件中?
我制作了一个绘图程序,绘图内容(来自System.drawing)绘制在面板上。我尝试了这个方法来做一个简单的保存,现在,我只得到一个空白图像 我的位图有其属性。RawData为0。我不知道这是否重要 当我隐藏屏幕并再次显示时,面板将变为空白 另一方面,当我调用面板的pnlpoint.Refresh()时,面板变为空白。这幅画丢了。这是一个双缓冲区的东西,就像它不保留值一样C# 如何保存Winforms面板';将图形内容添加到文件中?,c#,winforms,C#,Winforms,我制作了一个绘图程序,绘图内容(来自System.drawing)绘制在面板上。我尝试了这个方法来做一个简单的保存,现在,我只得到一个空白图像 我的位图有其属性。RawData为0。我不知道这是否重要 当我隐藏屏幕并再次显示时,面板将变为空白 另一方面,当我调用面板的pnlpoint.Refresh()时,面板变为空白。这幅画丢了。这是一个双缓冲区的东西,就像它不保留值一样 private bool Save() { Bitmap bmpDrawing;
private bool Save()
{
Bitmap bmpDrawing;
Rectangle rectBounds;
try
{
// Create bitmap for paint storage
bmpDrawing = new Bitmap(pnlPaint.Width, pnlPaint.Height);
// Set the bounds of the bitmap
rectBounds = new Rectangle(0, 0, bmpDrawing.Width, bmpDrawing.Height);
// Move drawing to bitmap
pnlPaint.DrawToBitmap(bmpDrawing, rectBounds);
// Save the bitmap to file
bmpDrawing.Save("a.bmp", ImageFormat.Bmp);
}
catch (Exception e)
{
MessageBox.Show("Error on saving. Message: " + e.Message);
}
return true;
}
我会跳过使用面板,它不像ImageBox那样是为图形设计的-继续使用它,然后您可以轻松保存内容 更新
图片盒。我已经有一段时间没有使用WinForms了:D这是一个最小的涂鸦程序,可以让你画持久线:
List<Point> curPoints = new List<Point>();
List<List<Point>> allPoints = new List<List<Point>>();
private void pnlPaint_MouseDown(object sender, MouseEventArgs e)
{
if (curPoints.Count > 1)
{
// begin fresh line or curve
curPoints.Clear();
// startpoint
curPoints.Add(e.Location);
}
}
private void pnlPaint_MouseUp(object sender, MouseEventArgs e)
{
if (curPoints.Count > 1)
{
// ToList creates a copy
allPoints.Add(curPoints.ToList());
curPoints.Clear();
}
}
private void pnlPaint_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
// here we should check if the distance is more than a minimum!
curPoints.Add(e.Location);
// let it show
pnlPaint.Invalidate();
}
private void pnlPaint_Paint(object sender, PaintEventArgs e)
{
// here you can use DrawLines or DrawCurve
// current line
if (curPoints.Count > 1) e.Graphics.DrawCurve(Pens.Red, curPoints.ToArray());
// other lines or curves
foreach (List<Point> points in allPoints)
if (points.Count > 1) e.Graphics.DrawCurve(Pens.Red, points.ToArray());
}
private void btn_undo_Click(object sender, EventArgs e)
{
if (allPoints.Count > 1)
{
allPoints.RemoveAt(allPoints.Count - 1);
pnlPaint.Invalidate();
}
}
private void btn_save_Click(object sender, EventArgs e)
{
string fileName = @"d:\test.bmp";
Bitmap bmp = new Bitmap(pnlPaint.ClientSize.Width, pnlPaint.ClientSize.Width);
pnlPaint.DrawToBitmap(bmp, pnlPaint.ClientRectangle);
bmp.Save(fileName, ImageFormat.Bmp);
}
List curPoints=new List();
列出所有点=新建列表();
私有void pnlpoint_MouseDown(对象发送方,MouseEventArgs e)
{
如果(curPoints.Count>1)
{
//重新开始直线或曲线
curPoints.Clear();
//起点
宵禁点。添加(如位置);
}
}
私有void pnlPaint_MouseUp(对象发送方,MouseEventArgs e)
{
如果(curPoints.Count>1)
{
//托利斯特创建了一个副本
allPoints.Add(curPoints.ToList());
curPoints.Clear();
}
}
私有void pnlpoint_MouseMove(对象发送方,MouseEventArgs e)
{
如果(e.Button!=MouseButtons.Left)返回;
//在这里,我们应该检查距离是否超过最小值!
宵禁点。添加(如位置);
//让它表现出来
pnlpoint.Invalidate();
}
私有void pnlPaint_Paint(对象发送方,PaintEventArgs e)
{
//在这里,您可以使用DrawLines或DrawCurve
//当前线路
如果(curPoints.Count>1)e.Graphics.DrawCurve(Pens.Red,curPoints.ToArray());
//其他直线或曲线
foreach(列出所有点中的点)
如果(points.Count>1)e.Graphics.DrawCurve(Pens.Red,points.ToArray());
}
私有无效btn\u撤消\u单击(对象发送方,事件参数e)
{
如果(allPoints.Count>1)
{
allPoints.RemoveAt(allPoints.Count-1);
pnlpoint.Invalidate();
}
}
私有无效btn\u保存\u单击(对象发送者,事件参数e)
{
字符串文件名=@“d:\test.bmp”;
位图bmp=新位图(pnlPaint.ClientSize.Width,pnlPaint.ClientSize.Width);
pnlPaint.DrawToBitmap(bmp,pnlPaint.ClientRectangle);
保存(文件名,ImageFormat.bmp);
}
添加您的保存代码,如果您有问题,请直接说出来
更新:我添加了两个代码段,分别执行保存和(无限)撤消操作
注1:确保使用双分叉控件:图片盒或标签,或带有on的面板
注2:这不支持单击创建点。由于没有绘图点
无论如何,如果需要,必须解决以下问题:
- 在当前曲线中只有一个点时,在距离鼠标点1像素处添加一个额外点李>
- 或者允许单个paoint并添加一个
以在FilleCircle
事件中显示它们Paint
文件夹中有一个实现,它支持方形和圆形画笔、橡皮擦和保存输出图像 实现问题属于堆栈溢出。问题出现在您未发布的代码中。您绘制面板的方式是错误的。使用它的绘制事件,不要使用CreateGraphics()。即使如此,我还是在用鼠标左键绘制,移动时需要抓取设备上下文。。因此,我认为最好在鼠标按下事件中传递它。我目前未成功使用面板的油漆事件。否。在
MouseDown
开始绘图后,MouseMove
可以收集点,但绘图必须发生在Paint
事件中,或从Paint
事件触发,否则DrawToBitmap
调用将导致无效。好的。我已经收集了分数。鼠标移动后如何调用绘制事件?pnlpoint.Refresh()/Invalidate()在面板再次变为空白之前将线条保留一秒钟。没有Winforms中的Imagebox那么薄。PictureBox具有强大的缩放和三层显示等功能,但目前的问题是基本绘图,这与Winforms非常相似,不是简单的保存问题。问题是关于“保存”图纸和空白面板是一个旁注,如OP所述。嗯,表面上,是的。但问题的原因是错误的绘画方式。保存的代码是/是正确的。对于一个实现,正面看GifRecorder/Controls/FreeDrawPanel.cs
大约有2.45万亿现成的解决方案。通过研究最小解学习是更好的方法,依我看。最小解
>>它是该代码的主键。;)我觉得这是解决这个问题的最好办法,尽管它仅限于划线。绘制图像、圆圈等会导致更严重的问题。但仅从我的问题来看,这是合适的。我想寻找更容易的控制,虽然这可以更容易地为所有绘画问题。我想我正在尝试做的是类似于微软的绘画,在上面投射图像,画线条,像素,形状,然后以999美元的价格出售。对于上面提到的问题,我喜欢这个。谢谢。这正是它的本来面目,但你可以把它作为基础。学习并扩展它!要继续进行更强大的绘图操作,您需要创建一个类DrawingAction
,并用List
替换List
。。DrawingAction
的属性包括:类型、颜色、笔和画笔、文本等。只需一步一个脚印。。!(有人这样做过吗