MFC技术内幕系列之(五)---MFC文档序列化内幕[2]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 bigwhite20xx 的 blog

        void store(carchive& ar) const;
 static cruntimeclass* pascal load(carchive& ar, uint* pwschemanum);
        const afx_classinit* m_pclassinit;
        ...//
   }
   其中两个重要函数store和load的源代码如下:这两个函数主要写和读a runtime class description,其中包括m_lpszclassname和m_wschema(版本号);
   //in arccore.cpp
   void cruntimeclass::store(carchive& ar) const
 // stores a runtime class description
   {
 word nlen = (word)lstrlena(m_lpszclassname);
 ar << (word)m_wschema << nlen;
 ar.write(m_lpszclassname, nlen*sizeof(char));
   }
   // loads a runtime class description
  cruntimeclass* pascal cruntimeclass::load(carchive& ar, uint* pwschemanum)
 
  {
 word nlen;
 char szclassname[64];

 word wtemp;
 ar >> wtemp; *pwschemanum = wtemp;
 ar >> nlen;

 // load the class name
 if (nlen >= _countof(szclassname) ||
  ar.read(szclassname, nlen*sizeof(char)) != nlen*sizeof(char))
 {
  return null;
 }
 szclassname[nlen] = '\0';

 // match the string against an actual cruntimeclass
 cruntimeclass* pclass = fromname(szclassname);
 if (pclass == null)
 {
  // not found, trace a warning for diagnostic purposes
  trace(traceappmsg, 0, "warning: cannot load %hs from archive.  class not                         defined.\n",szclassname);
 }

 return pclass;
   }
   下面看看那两个神秘的宏declare_serial和implement_serial吧!
   //in afx.h
   #define declare_serial(class_name) \
 _declare_dyncreate(class_name) \
 afx_api 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; } \
 afx_comdat afx_classinit _init_##class_name(runtime_class(class_name)); \
 _implement_runtimeclass(class_name, base_class_name, wschema, \
  class_name::createobject, &_init_##class_name) \
 carchive& afxapi operator>>(carchive& ar, class_name* &pob) \
  { pob = (class_name*) ar.readobject(runtime_class(class_name)); \
   return ar; } \
   宏的定义验证了上面的“基础”一说;
   下面是implement_serial进行初始化时的辅助结构afx_classinit及函数afxclassinit的定义:
   // generate static object constructor for class registration
  void afxapi afxclassinit(cruntimeclass* pnewclass);
  struct afx_classinit
 { afx_classinit(cruntimeclass* pnewclass) { afxclassinit(pnewclass); } };
  //in objcore.cpp
  void afxapi afxclassinit(cruntimeclass* pnewclass)
  {
 afx_module_state* pmodulestate = afxgetmodulestate();
 afxlockglobals(crit_runtimeclasslist);
 pmodulestate->m_classlist.addhead(pnewclass);
 afxunlockglobals(crit_runtimeclasslist);
  }
  有了前面文章的基础,在这里我就不详细将宏展开详解了,有了上面基础,我们就可以"真刀真枪"的读写文件了,比较起来“写文件”较容易,所以就让我们拿它先开刀吧!^_^

                       //////////////////////////////////////
                       /*        2.“写文件”        */
                       //////////////////////////////////////   
   大家都应该了解“写文件”的“导火索”是什么吧?你说对了"save"or"save as",下面我们就沿着这个导火索一路下行看看到底发生了什么吧?
    这里大家会发现一个小问题:那就是你在mfc应用程序向导为你做的sdi or mdi代码中找不到
"save"or"save as"功能项的处理函数,但它的功能却还能淋漓尽致的展现在你面前。这是为什么呢?原来这些函数是由cdocument类提供的。你的doc类继承cdocument类的同时也将这些处理函数完全集成了下来。下面我们就来看看他们的卢山真面目吧!
    当你按下"save"or"save as"功能键(包括菜单中的和工具栏中的)后,应用程序将调用
cmydoc::onfilesave() or cmydoc::onfilesaveas()(以后将只提及一个),但由于cmydoc类继承了其基类
cdocument的处理函数,所以实际调用的是cdocument::onfilesave();
 //in doccore.cpp
 void cdocument::onfilesave()
 {
 dofilesave();
 }
 bool cdocument::dofilesave()
 {
 dword dwattrib = getfileattributes(m_strpathname);
 if (dwattrib & file_attribute_readonly)
 {

本文关键:文档序列化
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top