If the retrieved type info is of type TKIND_ENUM or TKIND_MODULE, the cvars member of the TYPEATTR structure ( https://msdn.microsoft.com/en-us/library/windows/desktop/ms221003(v=vs.85).aspx ) contains the number of variables and the GetVarDesc method of the ITypeInfo interface retrieves a VARDESC structure ( https://msdn.microsoft.com/en-us/library/windows/desktop/ms221391(v=vs.85).aspx ) that describes the specified variable.
' =====================================================================================
' Retrieves information about constants
' =====================================================================================
FUNCTION CParseTypeLib.GetConstants (BYVAL pTypeInfo AS Afx_ITypeInfo PTR, BYVAL pTypeAttr AS TYPEATTR PTR, BYVAL hTreeView AS HWND, BYVAL hSubNode AS HTREEITEM) AS HRESULT
DIM hr AS HRESULT ' // HRESULT
DIM x AS LONG ' // Loop counter
DIM pVarDesc AS VARDESC PTR ' // Pointer to a VARDESC structure
DIM ptdesc AS TYPEDESC PTR ' // Pointer to a TYPEDESC structure
DIM cbstrName AS CBSTR ' // Name
DIM vtPtr AS tagVARIANT PTR ' // Pointer to a tagVARIANT structure
DIM cbstrTypeKind AS CBSTR ' // Type kind
DIM cbstrValue AS CBSTR ' // Value
DIM bstrLen AS LONG ' // Length of the unicode string
DIM wstrLen AS LONG ' // Length of the null-terminated unicode string
DIM hSubNode2 AS HTREEITEM ' // Sub node handle
IF pTypeInfo = NULL OR pTypeAttr = NULL THEN RETURN E_INVALIDARG
FOR x = 0 TO pTypeAttr->cVars - 1
hr = pTypeInfo->GetVarDesc(x, @pVarDesc)
IF hr <> S_OK OR pVarDesc = NULL THEN EXIT FOR
cbstrName.Clear
pTypeInfo->GetDocumentation(pVarDesc->memid, @cbstrName, NULL, NULL, NULL)
' // Some components use spaces in the names of enumeration members!
IF INSTR(**cbstrName, " ") THEN
cbstrName = AfxStrReplace(cbstrName, " ", "_")
END IF
' // Pointer to the variant that stores the value of the constant
vtPtr = pVarDesc->lpvarvalue
' // Gets the value of the constant
cbstrValue.Clear : cbstrTypeKind.Clear
cbstrValue = AfxVarToBstr(vtPtr)
cbstrTypeKind = TLB_VarTypeToConstant(pVarDesc->elemdescVar.tdesc.vt)
SELECT CASE pVarDesc->elemdescVar.tdesc.vt
CASE VT_I1, VT_UI1, VT_I2, VT_UI2, VT_I4, VT_UI4, VT_INT, VT_UINT
cbstrValue = **cbstrValue & " ' (&h" & HEX(VAL(**cbstrValue), 8) & ")"
CASE VT_BSTR, VT_LPSTR, VT_LPWSTR
' // cdosys.dll contains VT_BSTR constants
cbstrValue = CHR(34) & **cbstrValue & CHR(34)
CASE VT_PTR
ptdesc = pVarDesc->elemdescVar.tdesc.lptdesc
IF ptdesc THEN
' WORD PTR (null terminated unicode string)
' hxds.dll contains a module with these kind of constants.
IF ptdesc->vt = VT_UI2 THEN cbstrValue = CHR(34) & **cbstrValue & CHR(34)
END IF
' // Other types can be VT_CARRAY and VT_USERDEFINED, but don't have a typelib to test
END SELECT
hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, **cbstrName & " = " & **cbstrValue)
TreeView_AddItem(hTreeView, hSubNode2, NULL, "TYPE = " & cbstrTypeKind)
TreeView_AddItem(hTreeView, hSubNode2, NULL, "VALUE = " & cbstrValue)
TreeView_AddItem(hTreeView, hSubNode2, NULL, "ID = " & WSTR(pVarDesc->memid))
TreeView_Expand(hTreeView, hSubNode, TVE_EXPAND)
pTypeInfo->ReleaseVarDesc(pVarDesc)
pVarDesc = NULL
NEXT
IF pVarDesc THEN pTypeInfo->ReleaseVarDesc(pVarDesc)
END FUNCTION
' =====================================================================================
Modules can also contain string constants and declarations of functions and procedures of external DLLs. This is covered by the following code in the GetFunctions method.
hr = pTypeInfo->GetDllEntry(pFuncDesc->memid, pFuncDesc->invkind, @cbstrDllName, @cbstrEntryPoint, @wOrdinal)
IF hr = S_OK THEN
IF LEN(cbstrDllName) THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "DLL name = " & cbstrDllName)
IF LEN(cbstrEntryPoint) THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Entry point = " & cbstrEntryPoint)
IF wOrdinal THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Ordinal = " & WSTR(wOrdinal))
END IF