Визуальное программирование и MFC

       

Механизм записи и восстановления объектов


Рассмотрим предлагаемую MFC модель обмена данными между документом и файлом, в котором этот процесс идет через промежуточный объект-архив класса CArchive библиотеки MFC. Этот объект передается методу Serialize класса документа как параметр. Поэтому программист посылает данные не в файл, а в архив и читает из архива.

Метод Serialize класса документа вызывается объектами-архивами, когда приложение при необходимости читает или записывает состояние этого документа, вызывая методы CArchive::ReadObject и CArchive::WriteObject для объекта-архива. При этом методу Serialize передается ссылка на объект-архив, который и вызывает методы чтения или записи.

Из архива данные передаются в файл или читаются из файла. Объект-архив всегда связан с файлом (объектом класса CFile). Диалог при открытии и сохранении документа позволяет задать имя физического файла, хранящего данные документа. Затем создается объект класса CFile, который связывается с объектом архивом. Заметим, что создаваемый автоматически объект-архив существует на время выполнения только одной операции - чтения документа или записи документа, после чего разрушается.

Рассмотрим процесс записи и восстановления документа для однооконного или многооконного приложения, создаваемого средством AppWizard. При выборе команд Open, Save, SaveAs каркас приложения:

  • Выводит соответствующее диалоговое окно для получения имени файла от пользователя.
  • Открывает файл, указанный пользователем, как объект класса CFile. Создает объект-архив класса CArchive, связывая его с объектом файлом. Объект-архив получает статус "store" или "load", в зависимости от того, будет ли данные документа записываться или восстанавливаться из архива.
  • Вызывает метод Serialize, определенный в классе документа приложения, производном от класса CDocument, используя методы WriteObject или ReadObject для объекта-архива.
  • Определенный разработчиком приложения метод Serialize класса документа запишет значения переменных документа в архив.
    Через буфер архива данные передаются в файл, связанный с объектом-архивом.


  • Завершив сохранение документа, каркас приложения разрушит созданный объект-архив, а затем и объект-файл.


  • В этом процессе на разработчика приложения возлагается единственная обязанность - определить метод Serialize класса документа. Он отвечает только за то, какие переменные документа и как будут записываться в архив.

    Если программист сам организует процесс сериализации данных документа, то он сам должен проделать все перечисленные выше действия. Допустим, приложение выводит окно, которое имеет меню, содержащее пункты "Store" и "Load". Класс окна тогда имеет примерно следующее описание:

    // фрагмент файла определения класса class CMyWnd : public CFrameWnd { protected: CMyDoc *readDoc; // указатель на объект класса документа CMyDoc writeDoc; // объект класса документа

    protected: afx_msg void OnStore(); afx_msg void OnLoad(); DECLARE_MESSAGE_MAP() // другие описания класса ........................ };

    При выборе пользователем из меню пункта "Store" вызывается метод-обработчик OnStore, а при выборе пункта "Load" - метод-обработчик OnLoad. Приведем примеры организации процесса сохранения и восстановления документа.

    // фрагмент файла реализации класса BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd) ON_COMMAND(ID_LOAD, OnLoad) ON_COMMAND(ID_STORE, OnStore) END_MESSAGE_MAP() void CMyWnd::OnLoad() { // создание стандартной панели выбора файла Open CFileDialog DlgOpen(TRUE,NULL,NULL, OFN_HIDEREADONLY,(LPCSTR)"Все файлы (*.*)|*.*");

    // отображение стандартной панели выбора файла Open if(DlgOpen.DoModal()==IDOK) { // открытие файла для чтения CStdioFile File(DlgOpen.GetPathName(),CFile::modeRead);

    // связывание файла с объектом класса CArchive CArchive ar(&File,CArchive::load);

    // запись документа readDoc=(CMyDoc *)ar.ReadObject(RUNTIME_CLASS(CMyDoc));

    // закрыть объект ar и файл, связанный с ним ar.Close(); File.Close();

    // данные из переменных класса документа помещаются // в переменные класса окна ............................................. } } void CMyWnd::OnStore() { // создание стандартной панели выбора файла SaveAs CFileDialog DlgSaveAs(FALSE,NULL,NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, (LPCSTR)"Все файлы (*.*)|*.*");

    // отображение стандартной панели выбора файла SaveAs if(DlgSaveAs.DoModal()==IDOK) { // данные из переменных класса окна помещаются // в переменные класса документа ....................................................

    // открытие файла для записи CFile File(DlgSaveAs.GetPathName(), CFile::modeCreate|CFile::modeWrite);

    // связывание файла с объектом класса CArchive CArchive ar(&File,CArchive::store);

    // запись документа ar.WriteObject(&writeDoc);

    // закрыть объект ar и файл, связанный с ним ar.Close(); File.Close(); } } // другие методы класса .......................


    Содержание раздела