Control Persistence

I mentioned earlier that a control can choose to implement one or more of IPersistStorage, IPersistStream, and IPersistStreamInit. Because most controls maintain small data sets, they generally prefer and support stream-based persistence. Accordingly, a control container must be prepared to handle any one of these models, as the Component Cosmo sample in Chapter 8 demonstrated. CoCosmo's code prefers IPersistStorage over the others—most control containers will, however, prefer IPersistStreamInit, then IPersistStream, and then IPersistStorage. In addition, control containers must take OLEMISC_SETCLIENTSITEFIRST into account as well.

A control can also choose to support multiple persistence models for maximum flexibility, but the container determines which model is given preference. Some containers may give storage-based persistence priority and others may use streams first. Either way, a control gets its chance to save its own data.

Be aware that stream-based controls will not automatically support caching because the data cache is entirely storage-based. In other words, a control implementing IPersistStream[Init] need not and cannot support IOleCache2 itself or anything else to do with caching. This can markedly reduce the space required by the control as well as the time it takes to load a control in the first place. (This is because instantiating the cache does take a considerable amount of time.) The control should still be able to render a metafile or a bitmap for itself through IDataObject::GetData because a container might still want to cache presentations itself. Such a container can simply create its own data cache with CreateDataCache and manage it in a container-owned storage in which the control's own stream would be located.

A final note about persistence: Some containers do not store their forms in a binary format. Visual Basic, for example, saves a form as a straight-text file containing a description of the contents, including all control properties. A Visual Basic FRM file looks something like this:


VERSION 2.00
Begin Form ControlDialog
Caption = "Some Form"
ClientHeight = 1665
ClientLeft = 7035
ClientTop = 1710
ClientWidth = 3795
Height = 2040
Left = 6990
LinkTopic = "Form1"
ScaleHeight = 1665
ScaleWidth = 3795
Top = 1380
Width = 3885
Begin CommandButton DoThings
Caption = "&Do Things..."
Height = 495
Left = 240
TabIndex = 4
Top = 960
Width = 1095
End

§

To support saving properties as text in this manner, OLE Controls specifies that a control should be able to provide a property set (as we discussed in Chapter 16) through its IDataObject::GetData member. It should also reinitialize itself with that same property set through IDataObject::SetData. This specific property set has the format ID {FB8F0821-0164-101B-84ED-08002B2EC713}, the contents of which are documented in the CDK.