⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 13.4 可串行化的类.txt

📁 网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
💻 TXT
字号:
13.4 可串行化的类 

13.4.1 
实现类对串行化的支持


下面利用 Serialize函数来保存第 11章中己定义的CGraph对象。如果要用CArchive类保存一个对象
的话,那么这个对象的类必须支持串行化。一个可串行化的类通常都有一个Serialize成员函数。如
果要使一个类可串行化,可以经过以下五个步骤来实现。
由从CObject派生类(或从CObject派生的某个类派生); 
.重写Serialize成员函数:
③使用DECLARESERIAL宏(在类声明中)。该宏的声明形式如下所示: 
DECLARE_SERIAL( class_name ) 
其中参数class name就是想要成为可串行化类的类名。
④定义不带参数的构造函数:
(!)为类在实现文件中使用IMPLEMENT SERIAL宏。该宏的声明如下所示: 

IMPLEMENT_SERIAL( class_name , base_class_name, wSchema ) 
其中 class name参数是类的名称, base_class参数是基类的名称, wSchema是版本号。当从文件
		中读取对象数据时,需要对所保存的数据版本号进行判断,如果与当前CArchive对象的版本号一致,
则加载操作成功,否则失败。
因此,为了使用CA	rchive对象保存CGraph对象,首先要使CGraph类成为一个可串行化的类,再按照
上述步骤分别处理:
	①修改CGraph类的定义,让其从CObject派生,即在Graph.h文件中将CGraph类的定义修改为: 
class CGraph : public CObject 
CI1重载Serialize函数:
在Graph.h头文件中增加该函数的声明: 
void Serialize( CArchive& archive ) ; 
并在Graph.cpp源文件中实现这个函数,具体代码如例 13-19所示。
	void CGraph: :Serialize(CArchive& ar) 


if(ar.IsStoring()) 
ar<<m_nDrawType<<m-ptOrigin<<m-ptEnd ; 
else 
ar>>m_nDrawτype>>m-ptOrigin>>m-ptEnd; 
在如例13-19所示的Serialize函数中,首先判断CArchive对象: ar的状态,如果是存储,则保存
CGraph对象中图形三要素:绘制类型、绘制起点和终点:否则,就是加载数据,利用重载的提取操作
符获取数据。注意保存和提取数据的顺序。
③在声明CGraph类时,使用 DECLARE SERIAL宏,即在Graph.h头文件中,在 CGraph类定义的内部添
加下面这句宏调用的代码: 
DECLARE_SERIAL(CGraph) 
因为CGraph类定义一个不带参数的构造函数。因为现在CGraph类中正好有一个不带参数的构造函数,
所以不需要再定义了:
⑤为CGraph类在实现文件中使用IMPLEMENT SERIAL宏。即在Graph.cpp源文件中,在CGraph类的构造
函数前面添加下面这句宏调用的代码: 
IMPLEMENT_SERIAL(CGraph, CObject , 1 ) 
经过以上这几个步骤之后, CGraph类就支持串行化了,然后为此类再增加一个图形绘制函数: Draw,
从而将图形数据和图形绘制封装在一个类中,这也符合面向对象的思想。增加的Draw函数的实现代
码如例 13-20所示。 
19IJ 13-20 

void CGraph: : Draw(CDC *pDC) 
11创建透明画刷并选入设备描述表中 
CBrush 
*pBrush=CBrush : : FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); 
CBrush *pOldBrush=pDC->SelectObject(pBrush) ;
 11根据绘制类型绘制相应的图形 
switch(m_nDrawType) 
case 1: 
pDC->SetPixel(m-ptEnd ,RGB(O , O, O)) ; 
break; 

case 2: 
pDC->MoveTo(m-ptOrigin) ; 
pDC->LineTo(m-ptEnd) ; 
break; 

case 3: 
508 I 


pDC->Rectangle(CRect(m-ptOrigin , m-ptEnd)) ; break ; 
case 4: pDC一>E工lipse(CRect(m-ptOrigin,m-ptEnd)) ; break ; 
pDC->SelectObject(pOldBrush) ; 
在新增的Draw函数中,在绘制图形之前创建一个透明的画刷 CpBrush),并且前面已经介绍过, 
GetStockObject函数返回的是HGDIOBJ类型,而这里需要的是HBRUSH类型,因此需要进行强制转换。
接着,把新创建的透明画刷选入设备描述表中,并将返回的先前的画刷 CpOldBrush)保存起来。然
后,根据绘制类型绘制相应的图形:如果给制类型是1,贝IJ绘制一个点:如果是2,绘制一条直线:
如果是3,绘制一个矩形:如果是4,则绘制一个椭圆。在图形绘制完成之后,将先前的画刷 C 
p01dBrush )重新选入设备描述表中。
如果读者是重新创建的一个工程,而不是在第 11章己有程序上继续添加功能,这时可以把第11章中
己有程序的菜单资源复制过来。因为对第 11章的程序来说,其所有资源都是保存在Graphic.rc这个
文件中。我们可以在VC++集成环境中,利用【文件\打开】菜单命令,打开文件打开对话框,找到这
个文件并打开,即可在 VC++编辑环境中看到该程序所有的资源。如图 13.16所示。 
El 61 Graphic.rc 
@臼Accelerator 
ID D Bitmap 
@口Oialog 
ID D Icon 
8 61 Menu 
自·I'U.~'.!."I~Iil:fJ里!1:': I=-
ID 0 String T able 
回oToolbar 
因臼Version
图 13.16第 11章示例程序使用的资源

打开Menu分支,双击IDR MAINFRAME菜单资源,即可在资源编辑窗口打开这个菜单资源,在绘图子菜
单上单击鼠标右键,从弹出的快捷菜单中选择【复制】菜单项,然后在本章的工程中,切换到
ResourceView选项卡,打开IDR MAINFRAME菜单资源,在文件操作子菜单后单击鼠标右键,从弹出的
快捷菜单中选择【粘贴】菜单项,就完成了菜单资源的复制。在编程过程中,如果想复制资源的话,
都可以采用这种方式来实现,这样可以节省开发的时间。但是复制之后会有点问题:复制得到的这些
菜单项 E号可能不正确。不知道这是VC++的Bug呢,还是其他原因,笔者也没弄清楚。这时,我们只
有手工修改这些菜单项的 ID了。然后给绘图子菜单 F的四个菜单项分别添加命令响应,并添加 
LBUTTONDOWN和LBUTTONUP消息的响应函数。最后,还可以复制己有的第 11章程序中相应函数的实现
代码。之后,可以调整一下代码,删除无用的代码。

"‘ I 509 
第 13章文档与串市化 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -