Microsoft Visual Basic 3.00                            Microsoft Corporation
Technical Notes

TN001.TXT:  Support for DT_OBJECT Properties

This note describes how to use OLE Automation by creating a custom control
property whose data type is DT_OBJECT.

========================================================================

------------
Introduction
------------
The Visual Basic 3.0 Control Development Kit allows you to create custom
controls that support OLE Automation.  A custom control can define
a DT_OBJECT type property, whose value is a 4-byte pointer to an IDispatch
interface.  If your control can contain or refer to an OLE object, you
may want to expose this ability via a property of type DT_OBJECT.

This allows you to use Visual Basic statements such as:

	Dim MyObject As OBJECT
	Set MyObject = Control.Object
	MyObject.Method...

or, more directly:

	Control.Object.Method

----------------
Reference Counts
----------------
OLE has strict guidelines for maintaining reference counts on interface
pointers.  Functions that return interface pointers increment the reference
count on the pointer on behalf of the caller.  For example, calling
VBGetControlProperty for a DT_OBJECT property causes the returned
interface pointer to be incremented.  However, the caller is responsible
for eventually releasing the reference to the interface pointer
via IUnknown::Release().

If the property is PF_fGetMsg, you are responsible for incrementing the
reference count on the interface pointer you return in your VBM_GETPROPERTY
message code.

-------
Example
-------
You may want to create a control that is an OLE container, meaning that you
expose a pointer to an IDispatch interface via a DT_OBJECT property.
When the OLE object is initially created within the control, the control
could establish a connection to the OLE object by setting a pointer to an
IDispatch interface via IUnknown::QueryInterface().  The reference count for
the interface pointer would then be incremented from zero to one.

When the control is destroyed, or the control causes the OLE object
it contains to be released, the control would also need to release the
interface pointer using IUnknown::Release().  If the DT_OBJECT property is
PF_fGetData, then all reference count maintenance associated with fetching
the property is automatically handled by Visual Basic.  If, on the other hand,
the DT_OBJECT property is PF_fGetMsg, you would need to call
IUnknown::AddRef() on the interface pointer in your VBM_GETPROPERTY message
code.

If there is no valid IDispatch interface, VBGetControlProperty returns
NULL (DWORD 0).

--------------
Property Flags
--------------
Since the IDispatch interface pointer can be used only at run time,
you cannot save or load an interface pointer while saving or loading a form.
For this reason, you cannot use the PF_fSaveData flag on your DT_OBJECT
property.

You might want use to PF_fSaveMsg to enable you to do more sophisticated
processing at save or load time.  For example, you could handle
VBM_SAVEPROPERTY by serializing the OLE object corresponding to the
interface pointer into the form file, and handle VBM_LOADPROPERTY by
deserializing the object and getting a pointer to an IDispatch interface to
it to set your property.

A property defined as DT_OBJECT cannot be set.  This means that you cannot
use the property flags PF_fSetData or PF_fSetMsg.  In addition, you should
specify the PF_fNoRuntimeW flag for a DT_OBJECT property.

Since you cannot view or modify the value of a DT_OBJECT property at
design time, you should specify the PF_fNoShow flag for your DT_OBJECT 
property.

Note
----
You should not designate a DT_OBJECT property as the default property 
for your control.


