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)
{