如何将我在面板上绘制的形状保存为二进制 [英] How to save shapes which I draw on a Panel as binary

查看:50
本文介绍了如何将我在面板上绘制的形状保存为二进制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个迷你绘画程序。我想创建一个保存按钮,将面板详细信息(形状和正在绘制的所有内容)保存为二进制文件。我是这样做的:

I have a mini paint program . I want to create a save button which saves the panel details(shapes and everything that is been drawing) as a binary file. I did this:

 SaveFileDialog sfd = new SaveFileDialog();
 BinaryFormatter bf = new BinaryFormatter();
 var stream = new BinaryReader(File.Open(sfd.FileName,FileMode.Create));
 bf.Serialize(stream,object);

但它有一个错误,即使用对象在 bf中是无效的。 / code>。我应该怎么做?

but it has an error which using object is invalid in bf.Serialize. how should I do this?

推荐答案

您不需要序列化面板,面板无法序列化。您可以考虑以下任一选项:

You don't need to serialize the panel, a panel is not serializable. You can consider either of these options:


  1. 您可以在位图上绘制,然后保存位图,或者将控件绘制到图像上并保存图像。这样,您可以将所有形状展平为单个图像,并且在加载图像后它们不再是可编辑的形状。就像油漆。

  2. 您可以使形状可序列化,然后序列化文件中可序列化形状的列表。然后,您可以再次反序列化它们。这样,您可以加载形状并让用户对其进行编辑,例如Visio。

我在这里分享了两个示例:

I shared two examples here:


  • 保存图像示例:它只是将您在面板上绘制的图形保存到位图图像文件中。

  • Save Image Example: It simply saves the drawings which you painted on panel to a bitmap image file.

序列化示例:在此示例中,我创建了一些可序列化的形状类,其中包含一些属性,例如坐标和颜色,然后创建了 Save Load 方法,该方法允许您将形状序列化到文件中,还可以从文件中反序列化它们并再次显示它们。您可以简单地扩展此示例,以添加一些功能,例如命中测试和移动形状。您也可以使用xml序列化程序代替二进制序列化程序。

Serialization Example: In this example I've created some serializable shape classes containing some properties like coordinates and color, then I created a Save and Load method which allows you to serialize your shapes in a file and also deserialize them from the file and show them again. You can simply extend this example to add some functionality like hit-testing and moving shapes. Also you can use a an xml serializer instead of a binary serializer.

保存图像示例

在本示例中,为了简化起见,我只是将面板绘画保存在文件中。

To keep things simple in this example I just save panel paintings in a file.

如果将绘画逻辑放在面板的 Paint 事件中,则可以使用 DrawToBitmap 将控件的图像保存到文件:

If you put painting logic in Paint event of your panel, then you can use DrawToBitmap to save an image of your control to a file:

private void button1_Click(object sender, EventArgs e)
{
    using (var bm = new Bitmap(panel1.Width, panel1.Height))
    {
        panel1.DrawToBitmap(bm, new Rectangle(0, 0, bm.Width, bm.Height));
        bm.Save(@"d:\panel.bmp", System.Drawing.Imaging.ImageFormat.Bmp); 
    }
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.FillRectangle(Brushes.Red, 0, 0, 100, 100);
    e.Graphics.FillRectangle(Brushes.Blue, 50, 50, 100, 100);
}

序列化示例

您可以创建一些可序列化的形状,例如 LineShape RectangleShape ,它们来自可序列化的 Shape 类。我们在此类中存储形状的属性,这些类也包含绘制逻辑:

You can create some serializable shapes like LineShape and RectangleShape deriving from serializable Shape class. We store properties of shapes in this class, also these classes contain drawing logic:

[Serializable]
public abstract class Shape
{
    public abstract void Draw(Graphics g);
    public override string ToString() { return GetType().Name; }
}

[Serializable]
public class LineShape : Shape
{
    public LineShape(){ Color = Color.Blue; Width = 2; }
    public Point Point1 { get; set; }
    public Point Point2 { get; set; }
    public int Width { get; set; }
    public Color Color { get; set; }
    public override void Draw(Graphics g)
    {
        using (var pen = new Pen(Color, Width))
            g.DrawLine(pen, Point1, Point2);
    }
}

[Serializable]
public class RectangleShape : Shape
{
    public RectangleShape() { Color = Color.Red; }
    public Rectangle Rectangle { get; set; }
    public Color Color { get; set; }
    public override void Draw(Graphics g)
    {
        using (var brush = new SolidBrush(Color))
            g.FillRectangle(brush, Rectangle);
    }
}

您可以创建 ShapesList 类用于保存形状并包含用于保存和加载形状的逻辑。也是在表面上绘制所有形状的逻辑:

You can create a ShapesList class to hold shapes and contain logic for saving and loading shapes. Also the logic for painting all shapes on a surface:

[Serializable]
public class ShapesList : List<Shape>
{
    public void Save(string file)
    {
        using (Stream stream = File.Open(file, FileMode.Create))
        {
            BinaryFormatter bin = new BinaryFormatter();
            bin.Serialize(stream, this);
        }
    }
    public void Load(string file)
    {
        using (Stream stream = File.Open(file, FileMode.Open))
        {
            BinaryFormatter bin = new BinaryFormatter();
            var shapes = (ShapesList)bin.Deserialize(stream);
            this.Clear();
            this.AddRange(shapes);
        }
    }
    public void Draw(Graphics g)
    {
        this.ForEach(x => x.Draw(g));
    }
}

然后您可以使用这些形状和形状列表:

Then you can use these shapes and shapes list this way:

ShapesList Shapes;
private void Form3_Load(object sender, EventArgs e)
{
    Shapes = new ShapesList();
    Shapes.Add(new RectangleShape() { Rectangle = new Rectangle(0, 0, 100, 100), 
        Color = Color.Green });
    Shapes.Add(new RectangleShape() { Rectangle = new Rectangle(50, 50, 100, 100), 
        Color = Color.Blue });
    Shapes.Add(new LineShape() { Point1 = new Point(0, 0), Point2 = new Point(150, 150), 
        Color = Color.Red });
    this.panel1.Invalidate();
}

private void button1_Click(object sender, EventArgs e)
{
    Shapes.Save(@"d:\shapes.bin");
    Shapes.Clear();
    this.panel1.Invalidate();
    MessageBox.Show("Shapes saved successfully.");
    Shapes.Load(@"d:\shapes.bin");
    this.panel1.Invalidate();
    MessageBox.Show("Shapes loaded successfully.");
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    Shapes.Draw(e.Graphics);
}

这篇关于如何将我在面板上绘制的形状保存为二进制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆