• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            yehao's Blog

            使用 MFC 串行化數(shù)據(jù)和 C++ 對(duì)象

            轉(zhuǎn)自http://www.vckbase.com/document/viewdoc/?id=1871

            源代碼下載


            串行化數(shù)據(jù)
            串行化C++對(duì)象
            定制串行化

            串行化數(shù)據(jù)

            ——
            例子程序:Memo

              創(chuàng)建一個(gè)新的單文檔 SDI 應(yīng)用,視圖類選擇 CFormView,以便用戶可以在窗口中輸入。 在界面中創(chuàng)建三個(gè)編輯框,然后再添加三個(gè)相應(yīng)的編輯框變量。這三個(gè)變量是視圖類的成員變量,為了交互數(shù)據(jù),文檔類中也要?jiǎng)?chuàng)建三個(gè)對(duì)應(yīng)的變量。然后,文檔類和視圖類都要對(duì)數(shù)據(jù)成員進(jìn)行初始化操作,在文檔類中這個(gè)工作通常都在 OnNewDocument() 函數(shù)中進(jìn)行。因?yàn)橄旅嫒魏我粋€(gè)操作發(fā)生時(shí)都觸發(fā)文檔類 OnNewDocument()函數(shù)執(zhí)行:

            • 當(dāng)用戶啟動(dòng)應(yīng)用程序;
            • 當(dāng)用戶在“File”菜單中選擇“New”選項(xiàng);

            視圖類的初始化通常由 OnInitialUpdate() 負(fù)責(zé),下面的任何一個(gè)操作發(fā)生時(shí),代碼都會(huì)觸發(fā)視圖類 OnInitialUpdate()函數(shù)執(zhí)行 :

            • 當(dāng)用戶啟動(dòng)應(yīng)用程序;
            • 當(dāng)用戶在“File”菜單中選擇“New”選項(xiàng);
            • 當(dāng)用戶從“File”菜單中選擇 “Open”選項(xiàng);

            在視圖類中獲得文檔類指針的方法是:CFooDoc* pDoc = GerDocument();
            用此文檔指針便可以操作文檔類數(shù)據(jù):m_ViewData = pDoc->m_DocData;

            串行化的代碼很簡(jiǎn)單,ar 是一個(gè)與用戶選擇的文件相對(duì)應(yīng)的文檔對(duì)象(CArchive 對(duì)象):

            // CFooDoc 序列化
            void CFooDoc::Serialize(CArchive& ar)
            {
            if (ar.IsStoring())
            {
            // 將數(shù)據(jù)寫(xiě)入文件
            ar << m_DocData;
            }
            else
            {
            // 從文件中讀取數(shù)據(jù)
            ar >> m_DocData;
            }
            }

              這樣就將數(shù)據(jù)寫(xiě)入了文件,選擇“File”菜單中的“Save”或者“Save as”即可完成數(shù)據(jù)的串行化。 如果沒(méi)有保存數(shù)據(jù),退出程序是會(huì)提示用戶是否保存修改過(guò)的數(shù)據(jù)。具體細(xì)節(jié)請(qǐng)參考源代碼。

            串行化C++對(duì)象

            ——例子程序:PHN

            創(chuàng)建一個(gè)新的單文檔 SDI 應(yīng)用,視圖類選擇 CFormView,以便可以有窗口中用戶可以輸入。

            聲明一個(gè)要串行化的 C++ 類。如 CPhone;

            文檔類的處理:
              在文檔類中聲明一個(gè) MFC CObList 類對(duì)象,這個(gè)類很有用,功能也很強(qiáng),用它可以很輕松地維護(hù) C++ 對(duì)象列表,例如 添加、刪除列表元素等。在文檔類的頭文件中作如下聲明:

            CObList m_PhoneList;

              上面的聲明可以是 public 類型,這樣其它類可以直接訪問(wèn)它。也可以是 private 類型,這樣就必須聲明一個(gè)公共的訪問(wèn)函數(shù),比如:GetPhoneList(),這個(gè)函數(shù)能返回 m_PhoneList 的地址。

            通常可以在文檔類的 OnNewDocument()函數(shù)中進(jìn)行數(shù)據(jù)初始化;

            	// Create a CPhone Object
            CPhone* pPhone = new CPhone();
            pPhone->m_Name = "";
            pPhone->m_Phone = "";
            // Add new object to the m_PhoneList list
            m_PhoneList.AddHead(pPhone);		
              在此 CPhone 類的成員變量的初始化不是必須的,因?yàn)?CPhone 的構(gòu)造函數(shù)已經(jīng)完成了這個(gè)工作。AddHead()函數(shù)向 m_PhoneList 列表添加剛創(chuàng)建的 CPhone 對(duì)象。所以,無(wú)論什么時(shí)候創(chuàng)建新文檔(如啟動(dòng)應(yīng)用程序)都會(huì)向 m_PhoneList 列表中添加一個(gè)空的 CPhone 對(duì)象。注意類 CObList 的成員函數(shù) AddHead() 是向列表的“頭部”添加對(duì)象(列表的開(kāi)始),所以參數(shù)是想要添加的對(duì)象的地址。

            刪除 m_PhoneList 列表中的內(nèi)容

              因?yàn)?m_PhoneList 是在內(nèi)存中維護(hù)的,所以要隨時(shí)維護(hù),只要下面三個(gè)事件中的任何一個(gè)事件發(fā)生,都需要從內(nèi)存中刪除 m_PhoneList 列表中的對(duì)象:

            • 用戶退出應(yīng)用程序;
            • 用戶開(kāi)始一個(gè)新的文檔,如從“File”菜單中選擇“New”選項(xiàng);
            • 用戶打開(kāi)一個(gè)已存在的文檔,如從“File”菜單中選擇“Open”選項(xiàng);

            在文檔類的頭文件中聲明刪除操作的函數(shù):

            virtual void DeleteContents();

            其實(shí)現(xiàn)如下:

            // 刪除列表中的所有項(xiàng)目并釋放列表對(duì)象占用的內(nèi)存
            while ( ! m_PhoneList.IsEmpty() )
            {
            delete m_PhoneList.RemoveHead();
            }
            

            視圖類處理:

            聲明視圖類的數(shù)據(jù)成員:

            POSITION m_position; // 在文檔類列表中的當(dāng)前位置
            CObList* m_pList; // 指向文檔類的列表

            在 OnInitialUpdate()函數(shù)中初始化視圖類的數(shù)據(jù)成員

            	POSITION m_position;
            CObList* m_pList;
            // 獲取文檔類指針
            CFooDoc* pDoc = (CFooDoc*) GetDocument();
            // 獲得文檔類 m_PhoneList 的地址
            m_pList = &(pDoc->m_PhoneList);
            // 獲得列表頭位置
            m_position = m_pList->GetHeadPosition();
            // 用文檔類數(shù)據(jù)更新視圖類數(shù)據(jù)成員
            CPhone* pPhone = (CPhone*)m_pList->GetAt(m_position);
            m_Name = pPhone->m_Name;
            m_Phone = pPhone->m_Phone;
            // 用新的數(shù)據(jù)成員變量值更新屏幕顯示
            UpdateData(FALSE);
            // 控制輸入焦點(diǎn)
            ((CDialog*) this)->GotoDlgCtrl(GetDlgItem(IDC_NAME));
            

            更新文檔數(shù)據(jù)

            當(dāng)用戶修改了視圖類的數(shù)據(jù)成員,即修改了窗體編輯框中的內(nèi)容時(shí),執(zhí)行這些代碼后也會(huì)修改文檔類的數(shù)據(jù)成員。

            void CFooView::OnEnChangeName()
            {
            // 用屏幕輸入更新控件變量
            UpdateData(TRUE);
            // 獲得文檔指針
            CFooDoc* pDoc =(CFooDoc*)GetDocument();
            // 更新文檔
            CPhone* pPhone = (CPhone*)m_pList->GetAt(m_position);
            pPhone->m_Name = m_Name;
            // 置修改標(biāo)志為 TRUE
            pDoc->SetModifiedFlag();
            }
            

            在列表中移動(dòng)記錄,修改視圖類中相應(yīng)的函數(shù)。

            	// 聲明一個(gè)臨時(shí)的位置變量
            POSITION temp_pos;
            // 用當(dāng)前的列表位置更新 temp_pos
            temp_pos = m_position;
            // 用前一個(gè)/或后一個(gè)位置更新 temp_pos
            m_pList->GetPrev(temp_pos);
            if ( temp_pos == NULL)
            {
            // no previous element
            MessageBox(_T("Bottom of file encountered!"),_T("Phone for Windows"));
            }else
            {
            // 用列表前一個(gè)記錄內(nèi)容更新視圖成員數(shù)據(jù)
            m_position = temp_pos;
            CPhone* pPhone = (CPhone*)m_pList->GetAt(m_position);
            m_Name = pPhone->m_Name;
            m_Phone = pPhone->m_Phone;
            UpdateData(FALSE);
            }
            // 控制輸入焦點(diǎn)
            ((CDialog*) this)->GotoDlgCtrl(GetDlgItem(IDC_NAME));
            

            添加和刪除列表記錄:

            //添加記錄
            // 清空屏幕輸入控制
            m_Name = "";
            m_Phone = "";
            UpdateData(FALSE);
            // 創(chuàng)建一個(gè)新的  CPhone 對(duì)象
            CPhone* pPhone = new CPhone();
            pPhone->m_Name = m_Name;
            pPhone->m_Phone = m_Phone;
            // 添加新的對(duì)象到列表尾部,并用新的位置更新 m_position
            m_position = m_pList->AddTail(pPhone);
            // 獲得文檔指針
            CFooDoc* pDoc = (CFooDoc*) GetDocument();
            // 置修改標(biāo)志為 TRUE
            pDoc->SetModifiedFlag();
            // 控制輸入焦點(diǎn)
            ((CDialog*) this)->GotoDlgCtrl(this->GetDlgItem(IDC_NAME));
            //刪除記錄
            // 刪除前先保存舊的指針
            CObject* pOld;
            pOld = m_pList->GetAt(m_position);
            // 從列表中刪除元素
            m_pList->RemoveAt(m_position);
            // 從內(nèi)存中刪除對(duì)象
            delete pOld;
            // 如果列表已經(jīng)清空則添加一個(gè)空記錄
            if ( m_pList->IsEmpty())
            {
            OnBnClickedAddButton();
            }
            // 獲取文檔指針
            CPHNDoc* pDoc = (CPHNDoc*) GetDocument();
            // 置修改標(biāo)志為 TRUE
            pDoc->SetModifiedFlag();
            // 顯示列表的第一條記錄
            OnInitialUpdate();
            

            串行化處理

              我們要串行化 CPhone 對(duì)象,把C++對(duì)象寫(xiě)入文件,所以需要在 CPhone 類的定義和實(shí)現(xiàn)文件中加入相應(yīng)的串行化代碼,首先要在 CPhone 頭文件中加入一個(gè) MFC 宏,這是串行化需要的宏,必須為它提供一個(gè)參數(shù),也就是類的名字。

            // 串行化宏定義
            DECLARE_SERIAL(CPhone)
              其次是聲明串行化函數(shù),這個(gè)原型是必須的,因?yàn)橐谢?CPhone 對(duì)象列表,所以 CPhone 類必須有一個(gè)屬于自己的 Serialize()函數(shù):
            // 串行化函數(shù) Serialize()
            virtual void Serialize(CArchive& ar);
            

              在 CPhone 實(shí)現(xiàn)文件中也要加入對(duì)應(yīng)的代碼,這個(gè)宏也是串行化需要的另一個(gè)宏,它有三個(gè)參數(shù),第一個(gè)是類名,第二個(gè)是基類名,第三個(gè)是應(yīng)用程序的版本號(hào),可以將版本號(hào)定義為任何值,當(dāng)串行化數(shù)據(jù)到文件時(shí),此版本號(hào)也要寫(xiě)入文件。

            // 串行化宏實(shí)現(xiàn)
            IMPLEMENT_SERIAL(CPhone,CObject,0);
            串行化函數(shù) Serialize() 實(shí)現(xiàn)
            if (ar.IsStoring())
            {
            ar << m_Name << m_Phone;
            }
            else
            {
            ar >> m_Name >> m_Phone;
            }
            

            這里要注意的是為了使用 CObList 類的成員函數(shù) Serialize(),有幾個(gè)前提條件需要滿足:

            • 列表類對(duì)象必須是 MFC CObject 類的派生類對(duì)象,也就是說(shuō) CPhone 類必須是 CObject 的派生類;
            • 在列表中的對(duì)象類必須具備一個(gè)不帶參數(shù)的構(gòu)造函數(shù)。如果需要,也可以有其它帶參數(shù)的構(gòu)造函數(shù);
            • 必須聲明和實(shí)現(xiàn)列表類的串行化函數(shù) Serialize(),即 CPhone::Serialize();
            • 實(shí)現(xiàn)列表對(duì)象的串行化必須使用 DECLARE_SERIAL/IMPLEMENT_SERIAL 宏;

            調(diào)用列表 Serialize()函數(shù)

              這一步是串行化列表 m_PhoneList,也就是調(diào)用 m_PhoneList 的成員函數(shù) Serialize()。在什么地方調(diào)用呢?記住,無(wú)論用戶什么時(shí)候從“File”菜單中選擇“Save”或者“Save as”或“Open”選項(xiàng),都將執(zhí)行文檔類的 Serialize()函數(shù),所以必須在文檔類的 Serialize()函數(shù)中調(diào)用 m_PhoneList 的 Serialize()函數(shù)。
              這樣一來(lái),無(wú)論用戶什么時(shí)候從 File 菜單中選擇 Save/Save as 時(shí),都將把 m_PhoneList 保存在用戶選擇的文件中,同樣地,無(wú)論用戶什么時(shí)候從選擇 Open 時(shí),都將把文件中保存的列表信息加載到 m_PhoneList 中來(lái)。m_PhoneList 的串行化調(diào)用如下:

            m_PhoneList.Serialize(ar);

              只要在文檔類的 Serialize() 函數(shù)中調(diào)用上面這條語(yǔ)句時(shí),必須把 ar 作為參數(shù)傳入,它將完成需要串行化 m_PhoneList 列表數(shù)據(jù)的所有工作。不必在if語(yǔ)句中再做其它處理。

            定制串行化

            ——例子程序:ARCH

              串行化處理有時(shí)并不需要用戶選擇文件,此時(shí)仍要從或向一個(gè)特定文件串行化數(shù)據(jù),本部分將描述怎樣創(chuàng)建并定制一個(gè) CArchive 對(duì)象。創(chuàng)建一個(gè)新的單文檔 SDI 應(yīng)用, 工程名為 ARCH。視圖類仍然選擇 CFormView。視圖中兩個(gè)編輯框和兩個(gè)按鈕,編輯框用于輸入數(shù)據(jù),“Save to File”按鈕用于將輸入的數(shù)據(jù)串行化到文件,“Load from File”按鈕用于從文件中抽取數(shù)據(jù)。為簡(jiǎn)單起見(jiàn),文件使用的硬編碼。
            下面是 “Save to File”的操作代碼:

            	// 用屏幕輸入內(nèi)容更新 m_Var1 和 m_Var2
            UpdateData(TRUE);
            // 創(chuàng)建文件 C:\ARC.ARC
            CFile f;
            f.Open("c:\\arc.arc",CFile::modeCreate|CFile::modeWrite);
            // 創(chuàng)建一個(gè) CArchive 對(duì)象,并將文件與對(duì)象關(guān)聯(lián)
            CArchive ar(&f,CArchive::store);
            // 串行化 m_Var1 和 m_Var2 到文檔
            ar<<m_Var1<<m_Var2;
            // 關(guān)閉文檔
            ar.Close();
            // 關(guān)閉文件
            f.Close();
            

            下面是 “Load from File”的操作代碼:

            	// 打開(kāi)文件 C:\ARC.ARC
            CFile f;
            if ( f.Open("c:\\arc.arc",CFile::modeRead ) == FALSE )
            return;
            // 創(chuàng)建一個(gè) CArchive 對(duì)象,并將文件與對(duì)象關(guān)聯(lián)
            CArchive ar(&f,CArchive::load);
            // 從對(duì)象中抽取數(shù)據(jù)并賦值給成員變量
            ar>>m_Var1>>m_Var2;
            // 關(guān)閉文檔
            ar.Close();
            // 關(guān)閉文件
            f.Close();
            // 更新屏幕顯示
            UpdateData(FALSE);
            

              以上是三個(gè) MFC 串行化數(shù)據(jù)的例子,Memo 程序的功能是串行化數(shù)據(jù)到文件,Phn 程序是串行化 C++ 對(duì)象列表到文件,而 ARCH 則是定制串行化。詳細(xì)實(shí)現(xiàn)細(xì)節(jié)請(qǐng)下載源代碼。

            posted on 2011-05-15 17:28 厚積薄發(fā) 閱讀(345) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Windows編程

            導(dǎo)航

            <2025年6月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            統(tǒng)計(jì)

            常用鏈接

            留言簿

            隨筆分類

            文章分類

            文章檔案

            搜索

            最新評(píng)論

            婷婷久久综合九色综合绿巨人| 国产精品综合久久第一页| 亚洲色欲久久久久综合网 | 欧美喷潮久久久XXXXx| 久久亚洲精精品中文字幕| 国产精品久久久久天天影视| 色综合色天天久久婷婷基地| 亚洲精品无码久久不卡| 色综合久久久久无码专区| 久久精品国产只有精品2020| 久久只这里是精品66| 97久久香蕉国产线看观看| 久久久久亚洲AV综合波多野结衣 | 国产A级毛片久久久精品毛片| 久久亚洲AV成人无码电影| 精品久久久久久无码人妻热| 色综合久久中文字幕无码| 久久av高潮av无码av喷吹| 久久久久人妻精品一区二区三区 | 久久一区二区三区99| 欧美熟妇另类久久久久久不卡 | 国内精品免费久久影院| 久久男人Av资源网站无码软件 | 欧美喷潮久久久XXXXx| 亚洲国产精品成人久久蜜臀| 91精品国产91久久久久久蜜臀| 精品久久久中文字幕人妻| 亚洲精品美女久久久久99小说| 99久久精品免费国产大片| 国内精品久久久久久99蜜桃| 久久WWW免费人成一看片| 免费一级欧美大片久久网 | 日韩精品久久久久久久电影蜜臀| 久久精品二区| 九九久久精品无码专区| 99久久久久| 久久久WWW成人| 久久人搡人人玩人妻精品首页| 久久久久免费视频| 无码乱码观看精品久久| 免费精品国产日韩热久久|