Рисующее приложение в версии .NET, страница 7

Если вспомнить MFC, то там класс считается сериализуемым, если он является производным от класса CObject и в нем определена версия виртуальной функции Serialize. В библиотеке .NET Framework Classes используется несколько иной подход. Все типы данных, которые предполагается сериализовать, необходимо пометить атрибутом [Serializable]. Если объявление класса имеет этот атрибут, то все его поля данных могут быть последовательно (в двоичном, а возможно, и в SOAP-формате) помещены в файл. Сами операции записи (чтения) могут быть выполнены с помощью методов Serialize (Deserialize) класса BinaryFormatter (или SoapFormatter). Те поля данных класса, которые не нуждаются в сериализации следует пометить атрибутом [NonSerialized]. Логика сериализации иллюстрируется следующим фрагментом.

Man man = new Man();// Объявляем объект сериализуемого класса. Он должен иметь атрибут [Serializable]

Stream stream = File.Open ("Man.dat", FileMode.Create); // Создаем и открываем файл

BinaryFormatter fmt = new BinaryFormatter();// Создаем объект, способный вводить и выводить данные в двоичном формате

fmt.Serialize (stream, man); // Вывод всех данных класса, исключая те, которые имеют атрибут [NonSerialized]

stream.Close();

Продемонстрируем также процесс восстановления (но уже только сериализуемых) данных.

man = null; // Обнуляем объект

stream = File.Open ("Man.dat", FileMode.Open); // Открываем файл в режиме чтения

man = (Man)fmt.Deserialize(stream);

stream.Close();

С учетом сказанного мы продолжим развитие проекта Draw, введя в него новый класс Line. Для этого дайте команду Project4Add Class, задайте имя класса Line, имя файла: DrawDoc.cs и нажмите кнопку Finish. Имя файла задано с учетом того, что класс Line является вспомогательным, а главным классом будет класс DrawDoc, который реализует функции документа приложения. Мы создадим его позже. Введите в файл коды класса Line и директивы используемых пространств имен.

using System;

using System.IO;

using System.Collections;

using System.Drawing;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

using System.Windows.Forms;

namespace Draw

{

[Serializable]

public class Line

{

public ArrayList points = new ArrayList();        // Коллекция точек, параметры пера и обрамляющий прямоугольник

public float penWidth;

public Color penColor;

protected Rectangle rect;

public Rectangle Rect // Свойство "прямоугольник, обрамляющий линию"

{

get { return rect; }

set { rect = value; }

}

  public Line (Color c, float w) // Конструктор

{

penColor = c;

penWidth = w;

}

public void CalcRect()// Метод, вычисляющий прямоугольник линии

{

rect.Size = Size.Empty;

if (points.Count > 0)   // Если в линии есть точки

{

rect = new Rectangle ((Point)points[0], Size.Empty);

foreach (Point pt in points)

{

rect = Rectangle.FromLTRB (

pt.X < rect.Left ? pt.X : rect.Left,

pt.Y < rect.Top ? pt.Y : rect.Top,

pt.X > rect.Right ? pt.X : rect.Right,

pt.Y > rect.Bottom ? pt.Y : rect.Bottom

);

}

rect.Inflate ((int)penWidth, (int)penWidth); // Учет толщины линии

}

}

public void Draw (Graphics g) // Метод, изображающий линию

{

try

{

Pen pen = new Pen(penColor, penWidth);

for (int i=1;  i < points.Count;  i++)

g.DrawLine (pen, (Point)points[i-1], (Point)points[i]);

pen.Dispose();

}

catch (Exception e) { MessageBox.Show(e.ToString()); }

}

}

}

Прямоугольник, ограничивающий линию