您不需要序列化面板,面板是不可序列化的。您可以考虑以下任一选项:
- 您可以在位图上绘制然后保存位图,或者将控件绘制到图像并保存图像。这样,您会将所有形状展平为单个图像,并且在加载图像后它们不再是可编辑的形状。这就像油漆。
- 您可以使形状可序列化,然后在文件中序列化可序列化形状的列表。然后你可以再次反序列化它们。通过这种方式,您可以加载形状并让用户对其进行编辑,例如 Visio。
我在这里分享了两个例子:
保存图片示例
在这个例子中,为了简单起见,我只是将面板画保存在一个文件中。
如果您将绘画逻辑放在面板的Paint 事件中,那么您可以使用DrawToBitmap 将控件的图像保存到文件中:
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);
}
序列化示例
您可以创建一些可序列化的形状,例如从可序列化的Shape 类派生的LineShape 和RectangleShape。我们在这个类中存储形状的属性,这些类也包含绘图逻辑:
[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 类来保存形状并包含用于保存和加载形状的逻辑。还有在表面上绘制所有形状的逻辑:
[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));
}
}
那么你可以这样使用这些形状和形状列表:
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);
}