友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

深入浅出MFC第2版(PDF格式)-第52章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




                    11 00 22 00 33 00 44 00         ;CRect 



                    FF FF                           ;new class tag 

                    01 00                           ;schema 

                    07 00                           ;class name string length 

                    43 43 69 72 63 6C 65            ;〃CCircle〃 

                    55 00 66 00 77 00               ;CPoint & radius 



                    01 80                           ;old class tag 

                    02 00                           ;DWordArray size 

                    28 00 35 00                     ;point 

                    28 00 35 00                     ;point 



                    03 80                           ;old class tag 

                    11 00 22 00 33 00 44 00         ;CRect 



                    05 80                           ;old class tag 

                    55 00 66 00 77 00               ;CPoint & radius 



                    我希望有一个专门负责Serialization 的函数,就叫作Serialize 好了。假设现在我的Document 



                    类别名称为CScribDoc,我希望有这么便利的程序方法(请仔细琢磨琢磨其便利性): 



                   void CScribDoc::Serialize(CArchive& ar) 

                   { 

                       if (ar。IsStoring()) 

                           ar 》 m_sizeDoc; 

                       m_graphList。Serialize(ar); 

                   } 



                   void CObList::Serialize(CArchive& ar) 

                   { 

                       if (ar。IsStoring()) { 



164 


…………………………………………………………Page 227……………………………………………………………

                                                     第3章    MFC 六大關鍵技術之模擬 



        ar pNext) 

            ar data; 

    } 

    else { 

        WORD nNewCount; 

        ar 》》 nNewCount; 

        while (nNewCount……) { 

            CObject* newData; 

            ar 》》 newData; 

            AddTail(newData); 

        } 

    } 

} 



void CStroke::Serialize(CArchive& ar) 

{ 

    m_ptArray。Serialize(ar); 

} 



void CDWordArray::Serialize(CArchive& ar) 

{ 

    if (ar。IsStoring()) { 

        ar  nOldSize; 

        for (int i = 0; i 《 m_nSize; i++) 

            ar 》》 m_pData'i'; 

    } 

} 



void CRectangle::Serialize(CArchive& ar) 

{ 

    if (ar。IsStoring()) 

        ar 》 m_rect; 

} 



void CCircle::Serialize(CArchive& ar) 

{ 

    if (ar。IsStoring()) { 



                                                                                          165 


…………………………………………………………Page 228……………………………………………………………

                    第篇  勿在浮砂築高台 



                            ar 》 (WORD&)m_center。y; 

                            ar 》》 (WORD&)m_radius; 

                        } 

                    } 



                 每一个可写到文件或可从文件中读出的类别,都应该有它自己的Serailize  函数,负责它 



                 自己的资料读写文件动作。此类别并且应该改写》 运算子,把资料导流到 



                 archive  中。archive 是什么?是一个与文件息息相关的缓冲区,暂时你可以想象它就是 



                 文件的化身。当图3…3 的文件写入文件时,Serialize  函数的调用次序如图3…4 。 



                                  CMyDoc::Serialize 



                                   CObList::Serialize 



                                      如果串行元素是圆 

                                                          CStroke::Serialize 



                                                                CDWordArray::Serialize 



                                      如果串行元素是矩形 

                                                         CRectangle::Serialize 



                                      如果串行元素是线条 

                                                         CCircle::Serialize 



                     图3…4 图3…3 的文件内容写入文件时,Serialize 函数的调用次序。 



166 


…………………………………………………………Page 229……………………………………………………………

                                                         第3章    MFC 六大關鍵技術之模擬 



DECLARE_SERIAL / IMPLEMENT_SERIAL 宏 



     要将》 两个运算子多载化,还要让Serialize  函数神不知鬼不觉地放入类别声明 



     之中,最好的作法仍然是使用宏。 



     类别之能够进行文件读写动作,前提是拥有动态生成的能力,所以,MFC 设计了两个宏 



     DECLARE_SERIAL 和IMPLEMENT_SERIAL : 



      #define DECLARE_SERIAL(class_name)  

              DECLARE_DYNCREATE(class_name)  

              friend CArchive& AFXAPI operator》》(CArchive& ar; class_name* &pOb); 



      #define IMPLEMENT_SERIAL(class_name; base_class_name; wSchema)  

              CObject* PASCAL class_name::CreateObject()  

                      { return new class_name; }  

              _IMPLEMENT_RUNTIMECLASS(class_name; base_class_name; wSchema;  

                      class_name::CreateObject)  

              CArchive& AFXAPI operator》》(CArchive& ar; class_name* &pOb)  

                    { pOb = (class_name*) ar。ReadObject(RUNTIME_CLASS(class_name));  

                              return ar; }  



      为了在每一个对象被处理(读或写)之前,能够处理琐屑的工作,诸如判断是否第一次 



      出现、记录版本号码、记录文件名等工作,CRuntimeClass 需要两个函数Load 和Store 

                                                                                    : 

      struct CRuntimeClass 

      { 

      // Attributes 

              LPCSTR m_lpszClassName; 

              int m_nObjectSize; 

              UINT m_wSchema; // schema number of the loaded class 

              CObject* (PASCAL* m_pfnCreateObject)(); // NULL =》 abstract class 

              CRuntimeClass* m_pBaseClass; 



              CObject* CreateObject(); 

              void Store(CArchive& ar) const; 

              static CRuntimeClass* PASCAL Load(CArchive& ar; UINT* pwSchemaNum); 



              // CRuntimeClass objects linked together in simple list 

              static CRuntimeClass* pFirstClass; // start of class list 

              CRuntimeClass* m_pNextClass;     // linked list of registered classes 

      }; 



                                                                                            167 


…………………………………………………………Page 230……………………………………………………………

                    第篇  勿在浮砂築高台 



                    你已经在上一节看过Load  函数,当时为了简化,我把它的参数拿掉,改为由屏幕上获 



                    得类别名称,事实上它应该是从文件中读一个类别名称。至于Store  函数,是把类别名 



                    称写入文件中: 



                    // Runtime class serialization code 

                    CRuntimeClass* PASCAL CRuntimeClass::Load(CArchive& ar; UINT* pwSchemaNum) 

                    { 

                        WORD nLen; 

                        char szClassName'64'; 

                        CRuntimeClass* pClass; 



                        ar 》》 (WORD&)(*pwSchemaNum) 》》 nLen; 



                        if (nLen 》= sizeof(szClassName) || ar。Read(szClassName; nLen) != nLen) 

                                return NULL; 

                        szClassName'nLen' = '0'; 



                        for (pClass = pFirstClass; pClass != NULL; pClass = pClass…》m_pNextClass) 

                        { 

                            if (l
返回目录 上一页 下一页 回到顶部 0 1
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!