MFC ActiveX 控件:序列化

本文讨论如何序列化 ActiveX 控件。 序列化是读取或写入持久性存储媒体(例如磁盘文件)的过程。 Microsoft 基础类 (MFC) 库为 CObject 类中的序列化提供内置支持。 COleControl 通过使用属性交换机制将此支持扩展到 ActiveX 控件。

重要

ActiveX 是旧技术,不应用于新开发。 有关取代 ActiveX 的新式技术的详细信息,请参阅 ActiveX 控件

通过替代 COleControl::DoPropExchange 来实现 ActiveX 控件的序列化。 此函数在控件对象的加载和保存期间调用,可存储所有使用成员变量或使用带有更改通知的成员变量实现的属性。

以下主题涵盖了与序列化 ActiveX 控件相关的主要问题:

实现 DoPropExchange 函数

使用 ActiveX 控件向导生成控件项目时,会自动将多个默认处理程序函数添加到控件类,包括 COleControl::DoPropExchange 的默认实现。 以下示例展示了添加到使用 ActiveX 控件向导创建的类的代码:

void CMyAxUICtrl::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 CMyAxSerCtrl::DoPropExchange(CPropExchange* pPX)
{
   ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
   COleControl::DoPropExchange(pPX);
PX_Bool(pPX, _T("CircleShape"), m_bCircleShape, TRUE);
}

下表列出了可用于序列化控件属性的可能属性交换函数:

属性交换函数 目的
PX_Blob( ) 序列化二进制大型对象 (BLOB) 数据类型属性。
PX_Bool( ) 序列化布尔类型属性。
PX_Color( ) 序列化颜色类型属性。
PX_Currency( ) 序列化 CY(货币)类型属性
PX_Double( ) 序列化 double 类型属性。
PX_Font( ) 序列化字体类型属性。
PX_Float( ) 序列化 float 类型属性。
PX_IUnknown( ) 序列化 LPUNKNOWN 类型属性。
PX_Long( ) 序列化 long 类型属性。
PX_Picture( ) 序列化图片类型属性。
PX_Short( ) 序列化 short 类型属性。
PXstring( ) 序列化 CString 类型属性。
PX_ULong( ) 序列化 ULONG 类型属性
PX_UShort( ) 序列化 USHORT 类型属性

有关这些属性交换函数的详细信息,请参阅 MFC 参考中的 OLE 控件的持久性

自定义 DoPropExchange 的默认行为

DoPropertyExchange 的默认实现(如上一主题中所示)会调用基类 COleControl。 这会序列化 COleControl 自动支持的属性集,这将使用比仅序列化控件的自定义属性更多的存储空间。 通过删除此调用,可以让对象仅序列化你认为重要的属性。 保存或加载控件对象时,控件已实现的任何库存属性状态都不会被序列化,除非对它们显式添加 PX_ 调用

实现版本支持

版本支持使修改后的 ActiveX 控件能够添加新的持久性属性,并且仍然能够检测和加载由控件的早期版本所创建的持久状态。 若要使控件的版本作为其持久性数据的一部分,请在控件的 DoPropExchange 函数中调用 COleControl::ExchangeVersion。 如果使用 ActiveX 控件向导创建 ActiveX 控件,则会自动插入此调用。 如果不需要版本支持,可以将它删除。 不过,对于版本支持所提供的额外灵活性,控件大小的成本非常小(4 个字节)。

如果控件不是使用 ActiveX 控件向导创建的,请通过在 DoPropExchange 函数的开头插入以下行来添加对 COleControl::ExchangeVersion 的调用(在调用 COleControl::DoPropExchange 之前):

void CMyAxSerCtrl::DoPropExchange(CPropExchange* pPX)
{
   ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
   COleControl::DoPropExchange(pPX);
}

可以使用任意 DWORD 作为版本号。 ActiveX 控件向导生成的项目使用 _wVerMinor_wVerMajor 作为默认值。 这些是在项目的 ActiveX 控件类的实现文件中定义的全局常量。 在 DoPropExchange 函数的其余部分中,可以随时调用 CPropExchange::GetVersion 来检索正在保存或检索的版本。

在以下示例中,此示例控件的版本 1 只有“ReleaseDate”属性。 版本 2 添加“OriginalDate”属性。 如果指示控件从旧版本加载持久状态,则它会将新属性的成员变量初始化为默认值。

void CMyAxSerCtrl::DoPropExchange(CPropExchange* pPX)
{
   ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
   COleControl::DoPropExchange(pPX);

   PX_Long(pPX, _T("ReleaseDate"), m_ReleaseDate);
   if (pPX->GetVersion() >= MAKELONG(0, 2))
   {
      PX_Long(pPX, _T("OriginalDate"), m_OriginalDate);
   }
   else
   {
      if (pPX->IsLoading())
         m_OriginalDate = 0;
   }
}

默认情况下,控件将旧数据“转换”为最新格式。 例如,如果控件的版本 2 加载版本 1 保存的数据,则再次保存时,它将写入版本 2 格式。 如果希望控件以上次读取的格式保存数据,请在调用 ExchangeVersion 时将 FALSE 作为第三个参数传递。 第三个参数是可选的,默认为 TRUE

另请参阅

MFC ActiveX 控件