0

我有一个程序,用户可以在其中创建文本框,并将图像拖放到 Windows 窗体中的面板中,在这里用户可以移动图像、调整大小、删除它们等。基本上是一个非常简单的图像编辑器。

我想做的是让这项工作像一个非常简单的 PowerPoint 程序一样。

我正在尝试确定用户是否可以保存具有这些图像(在图片框中)和文本框的面板的内容。然后清除面板并使用新的图像和文本重新开始,但如果他们愿意,请返回上一个面板并进行编辑。

所以程序中的每个面板基本上都是 PowerPoint 中的幻灯片。

目前我可以将面板另存为 Jpeg 并存储这些,但这样我无法重新加载面板并像面板一样编辑内容。

我希望我已经在可以理解的程度上解释了这种情况。

是否可以做我正在尝试的事情,或者我应该以不同的方式解决问题?

4

2 回答 2

5

我要解决的方法是定义一个类,该类存储构成幻灯片的所有信息(因此,可以在代码中表示幻灯片),然后将幻灯片列表(称为演示文稿)序列化为XML 文件。

每张幻灯片都有可变数量的控件,可以是图像、文本框等,所以让我们先定义一个控件:

public class MySlideClass
{
    public class Control
    {
        public Point Position       { get; set; }
        public Size  Size           { get; set; }
        public Color Background     { get; set; }
        public Color Forground      { get; set; }
        public Image Picture        { get; set; }
        public string Text          { get; set; }
        public float TextSize       { get; set; }
        public Point TextPosition   { get; set; }
        // ...
        public float Transparency   { get; set; }
        public bool  Visible        { get; set; }

        public Control()
        {
        }
    }

    public class Slide
    {
        [XmlAttribute]
        public string Name          { get; set; }
        //
        public string Title         { get; set; }
        public Size Size            { get; set; }
        public Color Background     { get; set; }
        public Color Forground      { get; set; }
        public float Transparency   { get; set; }
        public bool Visible         { get; set; }

        public List<Control> Children { get; set; }

        public Slide()
        {
        }
    }


    public MySlideClass()
    {
    }
}

显然,您可以根据需要添加/删除属性。

注意{ get; set; }和 空的默认构造函数。您的类必须包含公共属性(使用 get/set 定义的变量)并具有一个空的默认构造函数,XMLSerializer以便能够序列化您的类(您仍然可以指定其他非空的构造函数)。

你会像这样使用这些类:

public void SaveSlideTest()
{
    // New control
    MySlideClass.Control newControl = new MySlideClass.Control();
    newControl.Position = new Point(20,30);
    newControl.Size     = new Size(75,25);
    newControl.Text     = "Image1";
    newControl.TextPosition= new Point(0,25);
    //ctl.Picture       = new Bitmap("image1.bmp");

    // Add control to children list
    List<MySlideClass.Control> childrenControls = new List<MySlideClass.Control>();
    childrenControls.Add(newControl);

    // New slide
    MySlideClass.Slide newSlide = new MySlideClass.Slide();
    newSlide.Name   = "Slide1";
    newSlide.Title  = "New Slide";
    newSlide.Size   = new Size(200,100);
    // Add child controls to slide
    newSlide.Children = childrenControls;

    // Add slide to presentation or 'slideshow'
    List<MySlideClass.Slide> mySlidePresentation = new List<MySlideClass.Slide>();
    mySlidePresentation.Add( newSlide );

    // Save presentation to XML
    SerializeObject("SavedSlidePresentation.xml",mySlidePresentation);
}

您的 SavedSlidePresentation.xml 看起来像:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfSlide xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Slide Name="Slide1">
    <Title>New Slide</Title>
    <Size>
      <Width>200</Width>
      <Height>100</Height>
    </Size>
    <Background />
    <Forground />
    <Transparency>0</Transparency>
    <Visible>false</Visible>
    <Children>
      <Control>
        <Position>
          <X>20</X>
          <Y>30</Y>
        </Position>
        <Size>
          <Width>75</Width>
          <Height>25</Height>
        </Size>
        <Background />
        <Forground />
        <Text>Image1</Text>
        <TextSize>0</TextSize>
        <TextPosition>
          <X>0</X>
          <Y>25</Y>
        </TextPosition>
        <Transparency>0</Transparency>
        <Visible>false</Visible>
      </Control>
    </Children>
  </Slide>
</ArrayOfSlide>

以下是序列化/反序列化函数:

public static List<MySlideClass.Slide> DeserializePresentation(string FileName)
{
    List<MySlideClass.Slide> returnList = new List<MySlideClass.Slide>();

    using(StreamReader streamReader = new StreamReader(FileName))
    {
        XmlSerializer xmlReader = new XmlSerializer(typeof(List<MySlideClass.Slide>));
        returnList = (List<MySlideClass.Slide>) xmlReader.Deserialize(streamReader);
    }
    return returnList;
}

// A generic object serializer
public static void SerializeObject(string Filename,object Obj)
{
    using(StreamWriter streamWriter = new StreamWriter(Filename))
    {
        XmlSerializer xmlSerializer = new XmlSerializer(Obj.GetType());
        xmlSerializer.Serialize(streamWriter,Obj);
    }
}

这应该比 a 更健壮Dictionary<TKey,TValue>

需要注意的一个重要方面:如果您决定将属性添加到 Slide 或 Control 类,则反序列化器将无法使用旧版本的数据类反序列化 XML 文件。

在这种情况下,您可以 1) 手动或以其他方式转换旧版本的 XML 文件,或者 2)ISerializable在您的类中实现接口(推荐)。

于 2013-07-08T18:43:54.703 回答
1

我之前做过一个类似的项目,我创建了两个字典来保存所有数据

// Dictionary which Holds all the Info for the shapes in a Particular Slide
Dictionary<Int32, ShapeInfo> slideInfoDict = new Dictionary<Int32, ShapeInfo>();

// Dictionary which Holds all the Info for the all the shapes in the all the slides
Dictionary<Int32, SlideInfo> appInfoDict = new Dictionary<Int32, SlideInfo>();

我的“ShapeInfo”类包含有关各种形状(表格、矩形、图像等)的所有信息。这个 shapeInfoDict 的键 (Int32) 是选定的形状。

“SlideInfo”类包含有关该特定幻灯片的所有信息。此 slideInfoDict 的键 (Int32) 被选中 Slide。

希望有帮助。

于 2013-07-08T11:17:25.563 回答