本文讨论序列化 ActiveX 控件的方法。序列化是从持久性存储媒体(如磁盘文件)中读取或向其中写入的进程。Microsoft 基础类 (MFC) 库在 CObject 类中为序列化提供内置支持。COleControl 通过使用属性交换机制,将此支持扩展到 ActiveX 控件。
通过重写 COleControl::DoPropExchange 实现 ActiveX 控件的序列化。在加载和保存控件对象期间调用此函数,以存储用成员变量或用带更改通知的成员变量实现的所有属性。用户可以对控件进行序列化以记录控件的状态。
下列主题介绍与序列化 ActiveX 控件相关的主要问题:
实现 DoPropExchange 函数
当使用“ActiveX 控件向导”生成控件项目时,几个默认处理函数被自动添加到控件类,包括 COleControl::DoPropExchange 的默认实现。下例显示添加到用“ActiveX 控件向导”创建的类的代码:
void CSampleCtrl::DoPropExchange( CPropExchange* pPX) { ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor)); COleControl::DoPropExchange(pPX); // TODO: Call PX_ functions for each persistent custom property. }
如果要使属性持久,则通过添加对属性交换函数的调用来修改 DoPropExchange
。下例说明自定义布尔 CircleShape 属性的序列化,这里 CircleShape 属性的默认值为 TRUE:
void CSampleCtrl::DoPropExchange(CPropExchange* pPX) { ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor)); COleControl::DoPropExchange(pPX); PX_Bool(pPX, "CircleShape", m_bCircleShape, TRUE); }
PX_Bool(pPX, "CircleShape", m_bCircleShape, TRUE);
第一个参数:指向CPropExchange类型变量的指针
第二个参数:属性名称
第三个参数:相应的成员变量
第四个参数:默认值,可选参数。
下表列出了可用于序列化控件属性的可能的属性交换函数:
属性交换函数 | 目的 |
---|---|
PX_Blob( ) | 序列化二进制大对象 (BLOB) 类型数据属性。 |
PX_Bool( ) | 序列化布尔类型属性。 |
PX_Color( ) | 序列化颜色类型属性。 |
PX_Currency( ) | 序列化 CY(货币)类型属性。 |
PX_Double( ) | 序列化 double 类型属性。 |
PX_Font( ) | 序列化 Font 类型属性。 |
PX_Float( ) | 序列化 float 类型属性。 |
PX_IUnknown( ) | 序列化 LPUNKNOWN 类型属性。 |
PX_Long( ) | 序列化 long 类型属性。 |
PX_Picture( ) | 序列化 Picture 类型属性。 |
PX_Short( ) | 序列化 short 类型属性。 |
PX_String( ) | 序列化 CString 类型属性。 |
PX_ULong( ) | 序列化 ULONG 类型属性。 |
PX_UShort( ) | 序列化 USHORT 类型属性。 |
有关这些属性交换函数的更多信息,请参见“MFC 参考”中的 OLE 控件的持久性。
自定义 DoPropExchange 的默认行为
DoPropertyExchange 的默认实现(如上一主题所示)调用 COleControl 基类。此操作序列化 COleControl 自动支持的属性集,所使用的存储空间比只序列化控件的自定义属性多。移除此调用使您的对象得以只序列化您认为重要的那些属性。保存或加载控件对象时,除非对控件已实现的任何常用属性状态显式添加 PX_ 调用,否则将不会序列化它们。
实现版本支持
版本支持使修订过的 ActiveX 控件得以添加新的持久性属性,并仍可以检测和加载由早期版本的控件创建的持久性状态。若要使控件的版本可用作其持久性数据的一部分,请在控件的 DoPropExchange
函数中调用 COleControl::ExchangeVersion。如果 ActiveX 控件是用“ActiveX 控件向导”创建的,则将自动插入此调用。如果不需要版本支持,可移除此调用。但是,控件大小的成本对于版本支持所提供的额外灵活性非常小(4 个字节)。
如果控件不是用“ActiveX 控件向导”创建的,则通过在 DoPropExchange
函数的开始处(在调用 COleControl::DoPropExchange 之前)插入下行来添加对 COleControl::ExchangeVersion 的调用:
void CSampleCtrl::DoPropExchange(CPropExchange* pPX) { ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor)); COleControl::DoPropExchange(pPX); ... }
可以使用任何 DWORD 作为版本号。“ActiveX 控件向导”所生成的项目使用 _wVerMinor 和 _wVerMajor 作为默认值。_wVerMinor 和 _wVerMajor 是在项目的 ActiveX 控件类的实现文件中定义的全局常数。在 DoPropExchange
函数的其余部分,可以随时调用 CPropExchange::GetVersion 检索正在保存或检索的版本。
在下例中,此示例控件的版本 1 仅有“ReleaseDate”属性。版本 2 添加了“OriginalDate”属性。如果指示控件从旧版本加载持久性状态,则控件将新属性的成员变量初始化为默认值。
void CSampleCtrl::DoPropExchange(CPropExchange* pPX) { ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor)); COleControl::DoPropExchange(pPX); PX_Long(pPX, "ReleaseDate", m_releaseDate); if (pPX->GetVersion() >= MAKELONG(0, 2)) { PX_Long(pPX, "OriginalDate", m_originalDate); } else { if (pPX->IsLoading()) m_originalDate = 0; } }
默认情况下,控件将旧数据“转换”成最新格式。例如,如果控件的版本 2 加载由版本 1 保存的数据,则数据再次保存时将写成版本 2 的格式。如果希望控件以上次读取的格式保存数据,则在调用 ExchangeVersion 时将 FALSE 作为第三个参数传递。此第三个参数是可选的,默认值为 TRUE。
另:属性页交换函数
属性页上的控件变量与ActiveX控件的属性建立联系使用DDP_ 函数。
如:DDP_Text(pDX,IDC_CODE,m_code,_T("CodeString")); 是将m_code与属性CodeString建立联系。
常用属性页交换函数:
函 数 名 |
函数的作用 |
DDP_CBIndex |
链接组合框中选定字符串的索引与控件属性 |
DDP_CBString |
链接组合框中的选定字符串与控件属性。所选字符串可以以与属性值相同的字母开始,但不必完全与其匹配 |
DDP_CBStringExact |
链接组合框中的选定字符串与控件属性。所选字符串和属性的字符串值必须完全匹配 |
DDP_Check |
链接复选框与控件属性 |
DDP_LBIndex |
链接列表框中选定字符串的索引与控件属性 |
DDP_LBString |
链接列表框中的选定字符串与控件属性。所选字符串可以以与属性值相同的字母开始,但不必完全与其匹配 |
DDP_LBStringExact |
链接列表框中的选定字符串与控件属性。所选字符串和属性的字符串值必须完全匹配 |
DDP_Radio |
链接单选按钮与控件属性 |
DDP_Text |
链接文本与控件属性 |