按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
{ { 。。。 } //源代码请看图8…5b
if (ar。IsStoring())
{ }
m_strokeList 是
else
{ } CObList 对象
1
m_strokeList。Serialize(ar);
}
//………………………………………………………………………………………………………… 到 的过程并非显而易见,
void CStroke::Serialize(CArchive& ar) 3 下一节将有详细说明。
{
if (ar。IsStoring()) {
ar 》 w; 5 CDWordArray::Serialize(Carchive& ar)
m_nPenWidth = w; { 。。。 } //源代码请看图8…5c
m_pointArray。Serialize(ar);
}
}
图8…5a Scribble Step1 的文件读写 (档)动作
502
…………………………………………………………Page 565……………………………………………………………
第8章 Document…View 深入探討
void CObList::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
CObject::Serialize(ar);
if (ar。IsStoring())
{
ar。WriteCount(m_nCount);
for (CNode* pNode = m_pNodeHead; pNode != NULL;
pNode = pNode…》pNext)
{ // J。J。Hou :针对串行中的每一个元素写文件
ASSERT(AfxIsValidAddress(pNode; sizeof(CNode)));
ar data;
}
这将引发CArchive 的多载
}
else else 运算子,稍后有深入说明。
{
DWORD nNewCount = ar。ReadCount();
CObject* newData;
while (nNewCount……)
{ //
J。J。Hou : 一一读入文件内容,加入串行
ar 》》 newData;
AddTail(newData);
}
}
}
图8…5b CObList::Serialize 源代码
void CDWordArray::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
CObject::Serialize(ar);
if (ar。IsStoring())
{
ar。WriteCount(m_nSize); //
把数组大小(元素个数)写入ar
ar。Write(m_pData; m_nSize * sizeof(DWORD)); //把整个数组写入ar
}
else
{
DWORD nOldSize = ar。ReadCount();
SetSize(nOldSize); // 从 ar 中读出数组大小(元素个数)
ar。Read(m_pData; m_nSize * sizeof(DWORD)); // ar ar ar
从 中读出整个数组
}
}
图8…5c CDWordArray::Serialize 源代码
503
…………………………………………………………Page 566……………………………………………………………
第篇 深入 MFC 程式設計
File/Save
【 】
CScribbleDoc 要求线条串行CObList 储存它自己
线条串行要求每个元素(也就是线条CStroke)储存它自己
经过多载运算子、虚拟函数等机制的运作;调用到CStroke::Serialize
CStroke 储存笔宽;并要求CArray 数组储存它自己
图8…5a则是以CDWordArray 为例来做解说(为了简化)
CArray::Serialize 将一个个CPoint写入磁盘中
Disk
图8…5d Scribble Document 的Serialize 动作细部分解。
实际看看储存在磁盘中的。SCB 文件内容,对Serialize 将会有深刻的体会。图8…6a 是
使用者在Scribble Step1 程序的绘图画面及存盘内容(以Turbo Dump 观察获得),图8
6b 是文件内容的解释。我们必须了解隐藏在MFC 机制中的serialization 细部动作,才
能清楚这些二进制数据的产生原由。如果你认为看倾印码(dump code )是件令人头晕的
事情,那么你会错失许多美丽事物。真的,倾印码使我们了解许多深层结构。
我在Scribble 中作画并存盘。为了突显笔宽的不同,我用了第10 章的Step3 版本,该版
本的Document 格式与Step1 的相同,但允许使用者设定笔宽。图8…6a 第一条线条的笔
宽是2 ,第二条是5,第三条是10,第四条是20 。文件储存于PENWIDTH。SCB 文件中。
504
…………………………………………………………Page 567……………………………………………………………
第8章 Document…View 深入探討
其实STEP1 并不能够改变
笔宽(但数据结构中已有笔
宽的考量),STEP3 才可
以改变笔宽。
CArchive::WriteObject
CArchive::ReadObject
Turbo Dump Version 3。1 Copyright (c) 1988; 1992 Borland International
Display of File PENWIDTH。SCB
000000: 01 00 07 00 43 53 74 72 6F 6B 65 02 。。。。。。。。CStroke。
04 00 FF FF
000010: 00 02 00 19 00 00 00 16 00 00 00 19 00 00 00 16 。。。。。。。。。。。。。。。。
000020: 00 00 00 01 80 05 00 03 00 18 00 00 00 2B 00 00 。。。。。。。。。。。。。+。。
000030: 00 18 00 00 00 2C 00 00 00 18 00 00 00 2C 00 00 。。。。。;。。。。。。。;。。
000040: 00 01 80 0A 00 02 00 18 00 00 00 48 00 00 00 18 。。。。。。。。。。。H。。。。
000050: 00 00 00 48 00 00 00 01 80 14 00 02 00 18 00 00 。。。H。。。。。。。。。。。。
000060: 00 64 00 00 00 18 00 00 00 64 00 00 00 。d。。。。。。。d。。。
图8…6a 在Scribble 中作画并存盘。PENWIDTH。SCB 文件全长109 个字节。
数值(hex) 说明
0004 表示此文件有四个CObList 元素。
FFFF FFFF 亦即…1,表示New Class Tag (稍后详述)。既然是新类别,
就得记录一些相关信息(版本号码和类别名称)
0001 这是Schema no。,代表对象的版本号码。此数值由
IMPLEMENT_SERIAL 宏的第三个参数指定。
0007 表示后面接着的「类别名称」有7 个字符。
43 53 74 72 6F 6B 65 〃CStroke〃 (类别名称)的ASCII 码。
0002 第一条线条的宽度。
0002 第一条线条的点数组大小(点数)。
00000019;00000016 第一条线条的第一个点坐标(CPoint 对象)。
00000019;00000016 第一条线条的第二个点坐标(CPoint 对象)。
505
…………………………………………………………Page 568……………………………………………………………
第篇 深入 MFC 程式設計
数值(hex) 说明
8001 这是(wOldClassTag | nClassIndex )的组合结果,表示接下来的对象