ActiveX Controls: Serializing

OverviewHow Do IFAQSample

This article discusses how to serialize an ActiveX control. Serialization is the process of reading from or writing to a persistent storage medium, such as a disk file. The Microsoft Foundation Class Library (MFC) provides built-in support for serialization in class CObject. COleControl extends this support to ActiveX controls through the use of a property exchange mechanism.

Serialization for ActiveX controls is implemented by overriding . This function, called during the loading and saving of the control object, stores all properties implemented with a member variable or a member variable with change notification.

The following topics cover the main issues related to serializing an ActiveX control:

  • Implementing DoPropExchange to serialize your control object

  • Customizing the serialization process

  • Implementing version support

Implementing the DoPropExchange Function

When you use ControlWizard to generate the control project, several default handler functions are automatically added to the control class, including the default implementation of . The following example shows the code added to classes created with ControlWizard:

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

   // TODO: Call PX_ functions for each persistent custom property.
}

If you want to make a property persistent, modify DoPropExchange by adding a call to the property exchange function. The following example demonstrates the serialization of a custom boolean CircleShape property:

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

   PX_Bool(pPX, "CircleShape", m_bCircleShape, TRUE);
}

The following table lists the possible property exchange functions you can use to serialize the control’s properties:

Property Exchange Functions Purpose
PX_Blob( ) Serializes a type Binary Large Object (BLOB) data property.
PX_Bool( ) Serializes a type Boolean property.
PX_Color( ) Serializes a type colorproperty.
PX_Currency( ) Serializes a type CY (currency) property.
PX_Double( ) Serializes a type double property.
PX_Font( ) Serializes a Font type property.
PX_Float( ) Serializes a type float property.
PX_IUnknown( ) Serializes a property of type LPUNKNOWN.
PX_Long( ) Serializes a type long property.
PX_Picture( ) Serializes a type Picture property.
PX_Short( ) Serializes a type short property.
PX_String( ) Serializes a type CString property.
PX_ULong( ) Serializes a type ULONG property.
PX_UShort( ) Serializes a type USHORT property.

For more information on these property exchange functions, see in the Class Library Reference.

Customizing the Default Behavior of DoPropExchange

The default implementation of DoPropertyExchange (as shown in the previous topic) makes a call to base class COleControl. This serializes the set of properties automatically supported by COleControl, which uses more storage space than serializing only the custom properties of the control. Removing this call allows your object to serialize only those properties you consider important. Any stock property states the control has implemented will not be serialized when saving or loading the control object unless you explicitly add PX_ calls for them.

Implementing Version Support

Version support enables a revised ActiveX control to add new persistent properties, and still be able to detect and load the persistent state created by an earlier version of the control. To make a control’s version available as part of the its persistent data, call in the control’s DoPropExchange function. This call is automatically inserted if the ActiveX control was created using ControlWizard. It can be removed if version support is not desired. However, the cost in control size is very small (4 bytes) for the added flexibility that version support provides.

If the control was not created with ControlWizard, add a call to COleControl::ExchangeVersion by inserting the following line at the beginning of your DoPropExchange function (before the call to COleControl::DoPropExchange):

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

You can use any DWORD as the version number. Projects generated by ControlWizard use _wVerMinor and _wVerMajor as the default. These are global constants defined in the implementation file of the project’s ActiveX control class. Within the remainder of your DoPropExchange function, you can call at any time to retrieve the version you are saving or retrieving.

In the following example, version 1 of this sample control has only a “ReleaseDate” property. Version 2 adds an “OriginalDate” property. If the control is instructed to load the persistent state from the old version, it initializes the member variable for the new property to a default value.

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;
    }
}

By default, a control “converts” old data to the latest format. For example, if version 2 of a control loads data that was saved by version 1, it will write the version 2 format when it is saved again. If you want the control to save data in the format last read, pass FALSE as a third parameter when calling ExchangeVersion. This third parameter is optional and is TRUE by default.