【转】第十三章 文档与串行化

阅读本文前,我们假设您已经:
         1,知道如何创建一个单文档的App Wizard
         2,知道C++ 类、函数重载等简单知识
         3,知道如何给View类或者Doc文档添加成员变量
         4,会用MFC的IDE调试工具最好,那么本文的程序您可以copy去调试 
         5,知道如何为某个框架类添加虚函数或消息处理函数
  

本课内容:

1,  首先讲解了一下什么是串行化,

2,  然后建立一个可串行化的类,并串行化之

一、  CArchive 和串行化

把对象(一个类)保存在永久性媒质上,比如磁盘。然后读取时,可以在内存中重新构建这个对象。把对象存储在磁盘的过程称为“串行化”。

一个Archive和一个文件相关,并且允许带缓冲的写和从存储器读出数据。

创建CArchive之前必须创一个一个CFile,必须保证CArchiveload/store状态和文件的打开模式相一致。一个文件只能有一个活动的CArchive

       当你创建一个CArchive对象时,和CFile或者其派生类关联来表示一个打开的文件。也可以指定CArchive是否是用来loadstoreArchive不仅可以处理基本类型,也可以处理CObject派生

CArchive的使用例子。

写入:
 CFile file("1.txt",CFile::modeCreate | CFile::modeWrite);
 CArchive ar(&file,CArchive::store);
 int i=4;
 float b=1.3f;   //C
默认用float定义而不加f的为double
 CString str="SongPeng";
 ar<<i<<b<<str;

读取:
 CFile file("1.txt",CFile::modeRead);
 CArchive ar(&file,CArchive::load);
 int i;
 float b;
 CString str;
 CString strRestult;
 ar>>i>>b>>str;
 strRestult.Format("%d %f %s",i,b,str);
 MessageBox(strRestult);

Note:读取和保存的格式、顺序要完全一致

二、  文档调用顺序

OnNewDocument()是虚函数。在程序运行之初构造文档,或是新建文档。

可以用GetDocString()函数获取IDR_MAINFRAME字符串的内容

修改Doc标题:

(1)     可以在其中设置文档标题SetTitle("XXXX")

(2)     String Table中修改标题字段

(3)     在新建工程的第四部advance选项中也能进行修改

点击“新建”后,先调用OnFileNew()函数,在OnFileNew中再调用OnNewDocument().

Void CwinApp::OnFIleNew(){

      If(m_pDocManager != NULL)m_pDocManager->OnFileNew();

}

OnNewDocument()函数内部调用过程:

1, voidCWinApp::OnFileNew()中调用CDocManager*类型的成员变量m_pDicManagerOnFileNew函数:

m_pDicManager->OnFileNew()

2, CDocManager::OnFileNew()中从文档链表取出文档指针。

(在这个OnFileNew中调用OpenDocumentFile(),以下两步都是本函数内语句)

pTemplate = (CDocTemplate*)m_templateList.GetHead();

执行pTemplate->OpenDocumentFile(NULL);语句

//调用单文档的OpenDocumentFile()

3, CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible)

(OpenDocumentFile中创建文档、视类、和框架类对象)

pDocument = CreateNewDocument();

pFrame = CreateNewFrame(pDocument, NULL);

if (!pDocument->OnNewDocument())

BOOL CGraphicDoc::OnNewDocument()

三、  串行化Serialize(CArchive &ar)

保存和读取数据的函数。点击“打开”或者“保存”菜单,最先调用此函数

执行例子:

if(ar.IsStoring())
 {ar<<m_nDrawType<<m_pOrigin<<m_pEnd;}
 else
 {  ar>>m_nDrawType>>m_pOrigin>>m_pEnd;}

我们文档类中调用Serialize保存一个可串行化的类的数据时实际上是利用了这个对象本身的Serialize函数,这个对象需要什么对象,都需要在你编写可串行化的类时去确定

OnFileOpen函数调用内部过程

void CWinApp::OnFileOpen()中调用

void CDocManager::OnFileOpen()中调用DoPromptFileName

在其中获得打开文件对话框,

然后回到CDocManager::OnFileOpen()中,再调用

AfxGetAp()->OpenDocumentFile();在其中初始化pOpenDocument指针,注意其中执行match=pTemplate->MatchDocType()查看是否有打开文档。如果文档已经打开,就不会调用Serialize()函数

 

生成可串行化的类的五个步骤:

A serializable class usually has a Serialize member function, and it usually uses the DECLARE_SERIAL and IMPLEMENT_SERIAL macros, as described under class CObject.
分为五步:
1 . Deriving your class from CObject (or from some class derived from CObject).
(即生成可串行化的类)
2 . Overriding the Serialize member function.
3 . Using the DECLARE_SERIAL macro in the class declaration. 
4 . Defining a constructor that takes no arguments.
5 . Using the IMPLEMENT_SERIAL macro in the implementation file for your class.
IMPLEMENT_SERIAL(CGraph,CObject,1),1
为版本号,保存和读取时版本号必须相同一个文档类对象能和多个视类对象相关,一个视类对象只和一个文档类对象相关.

 

CPtr类和CObArray类很相似,只是CObArray类的add增加的是CObject *指针类型。

类存入文件的例子

void CGraphicDoc::Serialize(CArchive& ar){

POSITION pos=GetFirstViewPosition();//多文档的时候,有多个view

CGraphicView *pView=(CGraphicView *)GetNextView(pos);
 if (ar.IsStoring()){

      int nCount=pView->m_obArray.GetSize();
      ar<<nCount;//
保存数目
      for(int i=0;i<nCount;i++){ar<<pView->m_obArray.GetAt(i);}

 }

 else {

int nCount;ar>>nCount;//读出数目
  CGraph *pGraph;
  for(int i=0;i<nCount;i++){ar>>pGraph;pView->m_obArray.Add(pGraph);}
 }
}

类对象存入数组

CGraph *pGraph=new CGraph(m_nDrawType,m_pOrigin,point);
 m_obArray.Add(pGraph);

一个文档来可以有多个相关的视类对象,而一个视类对象只能有一个文档类,要获得一个视类对象指针,就需要获得第一个视类对象在链表中的指针。然后通过POSITION值,调用GetNextView()不断获取视类对象

CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
 BOOL bMakeVisible)--->if (pDocument == NULL)--->if (pFrame == NULL)--->
if (lpszPathName == NULL)--->if (!pDocument->OnOpenDocument(lpszPathName))--->
BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName)---->
Serialize(loadArchive);---->void CGraphicDoc::Serialize(CArchive& ar)

 

    欢迎以任何形式转载本文,只要对您有用
    欢迎给我来信 webbery (at) sohu (dot) com (分别用@,.替换at,dot)

    韦伯主页: http://mail.ustc.edu.cn/~bywang(提供此笔记系列相关源程序下载)
    韦伯Blog: http://webbery.tianyablog.com
参考书目和网站: 
    (1)孙鑫VC++视频
    (2)1-6章主要参考: hbyufan的BLog
    (3)11-20章主要参考: songpeng的Blog
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值