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.