你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:技术专栏 / Linux开发
串行化(Serialization)(2)
 
当用户在界面上选择文件菜单/打开文件(ID_FILE_OPEN)时,CWinApp派生类的OnFileOpen函数被自动调用,它通过文档模板创建(MDI)/重用(SDI)框架、文档和视图对象,并最终调用CDocument::OnOpenDocument来读文件,CDocument::OnOpenDocument 的处理流程如下:    //示例代码4
    BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName)
    {
      if (IsModified())
        TRACE0("Warning: OnOpenDocument replaces an unsaved document.
");
    
      CFileException fe;
      CFile* pFile = GetFile(lpszPathName,
        CFile::modeRead|CFile::shareDenyWrite, &fe);
      if (pFile == NULL)
      {
        ReportSaveLoadException(lpszPathName, &fe,
          FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
        return FALSE;
      }
    
      DeleteContents();
      SetModifiedFlag(); // dirty during de-serialize
    
      CArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete);
      loadArchive.m_pDocument = this;
      loadArchive.m_bForceFlat = FALSE;
      TRY
      {
        CWaitCursor wait;
        if (pFile->GetLength() != 0)
          Serialize(loadArchive);   // load me
        loadArchive.Close();
        ReleaseFile(pFile, FALSE);
      }
      CATCH_ALL(e)
      {
        ReleaseFile(pFile, TRUE);
        DeleteContents();  // remove failed contents
    
        TRY
        {
          ReportSaveLoadException(lpszPathName, e,
            FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
        }
        END_TRY
        DELETE_EXCEPTION(e);
        return FALSE;
      }
      END_CATCH_ALL
    
      SetModifiedFlag(FALSE);   // start off with unmodified
    
      return TRUE;
    }

  同样,当用户选择菜单文件/文件保存(ID_FILE_SAVE)或者文件/另存为...(ID_FILE_SAVEAS)时,通过CWinApp::OnFileSave和CWinApp::OnFileSaveAs 最终调用CDocument::OnSaveDocument,这个函数处理如下:    //示例代码5
    BOOL CDocument::OnSaveDocument(LPCTSTR lpszPathName)
    {
      CFileException fe;
      CFile* pFile = NULL;
      pFile = GetFile(lpszPathName, CFile::modeCreate |
        CFile::modeReadWrite | CFile::shareExclusive, &fe);
    
      if (pFile == NULL)
      {
        ReportSaveLoadException(lpszPathName, &fe,
          TRUE, AFX_IDP_INVALID_FILENAME);
        return FALSE;
      }
    
      CArchive saveArchive(pFile, CArchive::store | CArchive::bNoFlushOnDelete);
      saveArchive.m_pDocument = this;
      saveArchive.m_bForceFlat = FALSE;
      TRY
      {
        CWaitCursor wait;
        Serialize(saveArchive);   // save me
        saveArchive.Close();
        ReleaseFile(pFile, FALSE);
      }
      CATCH_ALL(e)
      {
        ReleaseFile(pFile, TRUE);
    
        TRY
        {
          ReportSaveLoadException(lpszPathName, e,
            TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);
        }
        END_TRY
        DELETE_EXCEPTION(e);
        return FALSE;
      }
      END_CATCH_ALL
    
      SetModifiedFlag(FALSE);   // back to unmodified
    
      return TRUE;    // success
    }

  从前面两段代码可以看出,文件读和文件写的结构基本相同,并且最终都调用了CObject::Serialize函数完成对文档自己的读和写(参见注释中的save me和load me)。对于用AppWizard自动生成的MDI和SDI,系统自动生成了这个函数的重载实现,缺省的实现为:    //示例代码6
    void CMyDoc::Serialize(CArchive& ar)
    {
      if (ar.IsStoring())
      {
        // TODO: add storing code here
      }
      else
      {
        // TODO: add loading code here
      }
    }

  如果一个对VC非常熟悉的人,喜欢手工生成所有的代码(当然这是非常浪费时间也是没有必要的),那么他提供的CDocument派生类也应该实现这个缺省的Serialize函数,否则,系统在文件读写时只能调用CObject::Serialize,这个函数什么都不做,当然也无法完成对特定对象的文件保存/载入工作。当然,用户也可以截获ID_FILE_OPEN等菜单,实现自己的文件读写功能,但是这样的代码将变得非常烦琐,也不容易阅读。

(编辑:aniston)

  推荐精品文章

·2024年12月目录 
·2024年11月目录 
·2024年10月目录 
·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089