孫鑫:第十三講 用CArchive類讀取與保存文件

閱讀本文前,我們假設您已經:
   1,知道如何創建一個單文檔的App Wizard
   2,知道C++ 類、函數重載等簡單知識
   3,知道如何給View類或者Doc文檔添加成員變量
   4,會用MFC的IDE調試工具最好,那麼本文的程序您可以copy去調試
   5,知道如何爲某個框架類添加虛函數或消息處理函數
  
  本課內容:
  
  1, 首先講解了一下什麼是串行化,
  
  2, 然後建立一個可串行化的類,並串行化之
  
  一、 CArchive 和串行化
  
  把對象(一個類)保存在永久性媒質上,比如磁盤。然後讀取時,可以在內存中重新構建這個對象。把對象存儲在磁盤的過程稱爲“串行化”。
  
  一個Archive和一個文件相關,並且允許帶緩衝的寫和從存儲器讀出數據。
  
  創建CArchive之前必須創一個一個CFile,必須保證CArchive的load/store狀態和文件的打開模式相一致。一個文件只能有一個活動的CArchive。
  
  當你創建一個CArchive對象時,和CFile或者其派生類關聯來表示一個打開的文件。也可以指定CArchive是否是用來load或store。Archive不僅可以處理基本類型,也可以處理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<
  
  讀取:
   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_pDicManager的OnFileNew函數:
  
  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<
   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<
   for(int i=0;i<<PVIEW->m_obArray.GetAt(i);}
  
   }
  
   else {
  
  int nCount;ar>>nCount;//讀出數目
   CGraph *pGraph;
   for(int i=0;i>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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章