Adding Type Information

To add type information, you use the AddFuncDesc or AddVarDesc method of the ICreateTypeInfo interface.

Call AddFuncDesc to add a method to a dispatch interface or to add a property or method to a VTBL interface. Call AddVarDesc to add a property to a dispatch interface.

Each of these methods takes two parameters: an index for the new variable or function in the type description; and a pointer to a FUNCDESC or VARDESC structure that describes the new property or method.

The values of the fields in the function and variable descriptors depend on the type of interface you're working with and the property or method you're adding. For AddFuncDesc, build a function descriptor according to the values in the following table. See the  Automation Programmer's Reference for additional details.

Field

Description

Suggested Value

memid

Function member identifier; same as the DISPID.

MEMBERID_NIL. The ID will be assigned later by the LayOut method.

LprgScode

Valid return values for the function.

User-defined.

LprgElemdescParam

Array of parameter types.

User-defined.

Funckind

Type of function.

FUNC_PUREVIRTUAL or FUNC_DISPATCH

invkind

Invocation kind.

INVOKE_PROPERTYGET or INVOKE_FUNC

callconv

Calling convention.

CC_STDCALL

cParams

Total number of parameters.

User-defined.

cParamsOpt

Number of optional parameters.

User-defined.

oVft

Offset into virtual function table.

0. The VTBL address will be assigned later by the LayOut method.

cScodes

Number of return values in lprgScode.

User-defined.

elemdescFunc

ELEMDESC structure that gives the return type for the function.

User-defined.

wFuncFlags

FUNCFLAG enumeration that describes function.

Use FUNCFLAG_FSOURCE if the function is a source of events.


For AddVarDesc, build a variable descriptor according to the values in the following table. See the Automation Programmer's Reference for additional details.

Field

Description

Suggested Value

memid

Member identifier for the property; same as the DISPID.

MEMBERID_NIL. The ID will be assigned later by the LayOut method.

ElemdescVar

ELEMDESC structure that contains the type information for the property.

User-defined.

WVarFlags

VARFLAG enumeration that describes the property.

Use VARFLAG_FSOURCE if the property is a source of events.

Varkind

VARKIND enumeration that identifies the property.

VAR_DISPATCH


For both a function and a variable, specify an index of 0 to place the description at the front of the type information.

The following example builds a variable descriptor and adds a property to a dispatch interface. In the example, the property is one of a group of subobjects that the designer can create. The variable vd is a structure of type VARDESC and td is a structure of type TYPEDESC.

First, the example sets up some constants in the VARDESC structure. It specifies VAR_DISPATCH to indicate that it applies to a dispatch interface, and variable flags to show that it is a source of events and is read-only. This example also specifies its own DISPIDs, rather than allowing the Layout method to assign them.

vd.memid = index + DISPID_CUSTOMOFFSET;
vd.varkind = VAR_DISPATCH;
vd.wVarFlags = VARFLAG_FSOURCE | VARFLAG_FREADONLY;

Next, it adds a reference to the new property's type information:

hr = m_state.pRuntimeDispinterface->AddRefTypeInfo(
                                    m_state.pObjectTI, &href);
    

With the handle to the referenced type information in href, the rest of the variable and type descriptors can be filled in. The variable descriptor is then passed to AddVarDesc to add the new type information:

td.vt = VT_USERDEFINED;
td.hreftype = href;
vd.elemdescVar.tdesc.lptdesc = &td;
vd.elemdescVar.tdesc.vt = VT_PTR;
hr = m_state.pRuntimeDispinterface->AddVarDesc(0, &vd);

After adding the property, you should set its name. The code fragment below keeps the names of the subobjects in the global structure m_state, and retrieves it from there to pass to the SetVarName method:

bstrName = m_state.rgObjects[index].bstrName;
hr =  m_state.pRuntimeDispinterface->SetVarName(0, bstrName);

Finally, you must lay out the new type information. See "Laying Out the Type Information" later in this chapter.