导航:  COM (Component Object Model) > The making of a type library browser >

Retrieving the parameters

上一页返回章节概述下一页

One of the members of the FUNDESC structure, cParams, contains the number of parameters of each function or method. Parameters can be of any kind of data type and be passed by value or by reference. And so the fun continues!

 

' =====================================================================================

' Retrieve information about the parameters

' =====================================================================================

FUNCTION CParseTypeLib.GetParameters (BYVAL pTypeInfo AS Afx_ITypeInfo PTR, BYVAL pFuncDesc AS FUNCDESC PTR, _

BYVAL hTreeView AS HWND, BYVAL hSubNode2 AS HTREEITEM, BYVAL bVTableView AS BOOLEAN) AS HRESULT

 

 DIM hr AS HRESULT                       ' // HRESULT

 DIM y AS LONG                           ' // Loop counter

 DIM hParamsNode AS HTREEITEM            ' // Parameters node

 DIM hParamNameNode AS HTREEITEM         ' // Parameter name node

 DIM cNames AS DWORD                     ' // Number of names returned by ITypeInfo.GetNames

 DIM pParam AS ELEMDESC PTR              ' // Pointer to an array of parameters

 DIM wFlags AS WORD                      ' // Parameter flags

 DIM cbstrParamName AS CBSTR             ' // Parameter name

 DIM pParamTypeAttr AS TYPEATTR PTR      ' // Referenced TYPEATTR structure

 DIM pReturnTypeAttr AS TYPEATTR PTR     ' // Referenced TYPEATTR structure

 DIM cbstrVarType AS CBSTR               ' // Variable type

 DIM cbstrTypeKind AS CBSTR              ' // Type kind

 DIM cbstrFBKeyword AS CBSTR             ' // FB keyword

 DIM cbstrFBSyntax AS CBSTR              ' // FB syntax

 DIM wIndirectionLevel AS WORD           ' // Indirection level

 DIM pRefTypeInfo AS Afx_ITypeInfo PTR   ' // Referenced TypeInfo interface

 DIM ptdesc AS TYPEDESC PTR              ' // Pointer to a TYPEDESC structure

 

 hParamsNode = TreeView_AddItem(hTreeView, hSubNode2, NULL, "Number of parameters = " & WSTR(pFuncDesc->cParams))

 ' ----------------------------------------------------------------------------------

 ' Gets the name of all the parameters.

 ' The first one is the name of the function.

 ' If the member ID identifies a property that is implemented with property functions,

 ' the property name is returned. For property get functions, the names of the function

 ' and its parameters are always returned.

 ' For property put and put reference functions, the right side of the assignment is

 ' unnamed. If cMaxNames is less than is required to return all of the names of the

 ' parameters of a function, then only the names of the first cMaxNames-1 parameters

 ' are returned. The names of the parameters are returned in the array in the same

 ' order that they appear elsewhere in the interface (for example, the same order in

 ' the parameter array associated with the FUNCDESC enumeration).

 ' ----------------------------------------------------------------------------------

 REDIM rgbstrNames(pFuncDesc->cParams) AS AFX_BSTR

 hr = pTypeInfo->GetNames(pFuncDesc->memid, @rgbstrNames(0), pFuncDesc->cParams + 1, @cNames)

 IF hr = S_OK THEN

    ' // Pointer to an ELEMDESC structure

    pParam = pFuncDesc->lprgelemdescParam

    ' // Retrieves information about the parameters

    FOR y = 0 TO pFuncDesc->cParams - 1

       cbstrVarType.Clear : cbstrTypeKind.Clear : cbstrFBKeyword.Clear

       ' // Attributes

       wFlags = pParam[y].paramdesc.wParamFlags

       ' // When using the automation view, it does not return a name for the return type

       cbstrParamName.Clear

       cbstrParamName = rgbstrNames(y + 1)

       IF LEN(cbstrParamName) = 0 THEN

          IF y = pFuncDesc->cParams - 1 THEN

             cbstrParamName = "rhs"

          ELSE

             cbstrParamName = "prm" & WSTR(y + 1)

          END IF

       END IF

       hParamNameNode = TreeView_AddItem(hTreeView, hParamsNode, NULL, cbstrParamName)

       TreeView_AddItem(hTreeView, hParamNameNode, NULL, "Attributes = " & WSTR(wFlags) & " [&h" & HEX(wFlags, 8) & "] " & TLB_ParamflagsToStr(wFlags))

       wIndirectionLevel = 0

       IF pParam[y].tdesc.vt = VT_USERDEFINED THEN

          ' // If it is a user defined type, retrieve its name

          hr = pTypeInfo->GetRefTypeInfo(pParam[y].tdesc.hreftype, @pRefTypeInfo)

          IF hr = S_OK AND pRefTypeInfo <> NULL THEN

             cbstrVarType.Clear

             hr = pRefTypeInfo->GetDocumentation(-1, @cbstrVarType, NULL, NULL, NULL)

             hr = pRefTypeInfo->GetTypeAttr(@pParamTypeAttr)

             IF hr = S_OK AND pParamTypeAttr <> NULL THEN

                IF pParamTypeAttr->typekind = TKIND_ALIAS THEN

                   cbstrTypeKind = TLB_TypeKindToStr(pParamTypeAttr->typekind) & " | " & TLB_VarTypeToConstant(pParamTypeAttr->tdescalias.vt)

                ELSE

                   cbstrTypeKind = TLB_TypeKindToStr(pParamTypeAttr->typekind)

                END IF

                TreeView_AddItem(hTreeView, hParamNameNode, NULL, "TypeKind = " & cbstrTypeKind)

                pRefTypeInfo->ReleaseTypeAttr(pParamTypeAttr)

                pParamTypeAttr = NULL

             END IF

             IF pRefTypeInfo THEN pRefTypeInfo->Release

          END IF

       ELSEIF pParam[y].tdesc.vt = VT_PTR THEN

          ' // Pointer to a TYPEDESC structure

          ptdesc = pParam[y].tdesc.lptdesc

          wIndirectionLevel = 1

          DO

             SELECT CASE ptdesc->vt

                ' // If it is a pointer, do it again

                CASE VT_PTR

                   wIndirectionLevel += 1

                   ptdesc = ptdesc->lptdesc

                CASE VT_USERDEFINED

                   ' // Retrieve the name of the user defined type

                   hr = pTypeInfo->GetRefTypeInfo(ptdesc->hreftype, @pRefTypeInfo)

                   IF hr = S_OK AND pRefTypeInfo <> NULL THEN

                      cbstrVarType.Clear

                      hr = pRefTypeInfo->GetDocumentation(-1, @cbstrVarType, NULL, NULL, NULL)

                      hr = pRefTypeInfo->GetTypeAttr(@pParamTypeAttr)

                      IF hr = S_OK AND pParamTypeAttr <> NULL THEN

                         IF pParamTypeAttr->typekind = TKIND_ALIAS THEN

                            cbstrTypeKind = TLB_TypeKindToStr(pParamTypeAttr->typekind) & " | " & TLB_VarTypeToConstant(pParamTypeAttr->tdescalias.vt)

                         ELSE

                            cbstrTypeKind = TLB_TypeKindToStr(pParamTypeAttr->typekind)

                         END IF

                         TreeView_AddItem(hTreeView, hParamNameNode, NULL, "TypeKind = " & cbstrTypeKind)

                         pRefTypeInfo->ReleaseTypeAttr(pParamTypeAttr)

                         pParamTypeAttr = NULL

                      END IF

                      IF pRefTypeInfo THEN pRefTypeInfo->Release

                   END IF

                   EXIT DO

                CASE ELSE

                   ' // Get the equivalent type

                   cbstrVarType = TLB_VarTypeToConstant(ptdesc->vt)

                   cbstrFBKeyword = TLB_VarTypeToKeyword(ptdesc->vt)

                   EXIT DO

             END SELECT

          LOOP

       ELSE

          ' // Get the equivalent type

          cbstrVarType = TLB_VarTypeToConstant(pParam[y].tdesc.vt)

          cbstrFBKeyword = TLB_VarTypeToKeyword(pParam[y].tdesc.vt)

          ' // Increment indirection level to pointers

          IF cbstrTypeKind = "TKIND_INTERFACE" OR cbstrTypeKind = "TKIND_DISPATCH" OR cbstrTypeKind = "TKIND_COCLASS" THEN wIndirectionLevel += 1

          IF cbstrVarType = "VT_SAFEARRAY" THEN wIndirectionLevel += 1

       END IF

       TreeView_AddItem(hTreeView, hParamNameNode, NULL, "Indirection level = " & WSTR(wIndirectionLevel))

       TreeView_AddItem(hTreeView, hParamNameNode, NULL, "VarType = " & cbstrVarType)

       ' // Add a prefix to structures that begin with an underscore

'         IF LEFT$(cbstrVarType, 1) = "_" THEN

'            IF cbstrTypeKind = "TKIND_RECORD" OR cbstrTypeKind = "TKIND_UNION" THEN cbstrVarType = s" & cbstrVarType

'         END IF

       ' // Parameter name, type and indirection

       ' // TODO: IF bVTableView = TRUE then use CBSTR and CVARIANT

       SELECT CASE **cbstrTypeKind

          CASE "TKIND_INTERFACE", "TKIND_DISPATCH", "TKIND_COCLASS"

             IF wIndirectionLevel = 2 THEN

                cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS " & **cbstrVarType & " PTR PTR"

             ELSE

                cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS " & **cbstrVarType & " PTR"

             END IF

          CASE "TKIND_RECORD", "TKIND_UNION", "TKIND_ENUM"

             IF wIndirectionLevel = 2 THEN

                cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS " & **cbstrVarType & " PTR PTR"

             ELSEIF wIndirectionLevel = 1 THEN

                cbstrFBSyntax = "BYVAL " & **cbstrParamName &  " AS " & **cbstrVarType & " PTR"

             ELSE

                cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS " & **cbstrVarType

             END IF

          CASE ELSE

             IF LEFT(**cbstrTypeKind, 11) = "TKIND_ALIAS" THEN

                IF wIndirectionLevel = 2 THEN

                   cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS " & **cbstrVarType & " PTR PTR"

                ELSEIF wIndirectionLevel = 1 THEN

                   cbstrFBSyntax = "BYVAL " & **cbstrParamName &  " AS " & **cbstrVarType & " PTR"

                ELSE

                   cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS " & **cbstrVarType

                END IF

             ELSE

                SELECT CASE **cbstrVarType

                   CASE "VT_UNKNOWN"

                      IF wIndirectionLevel = 2 THEN

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS IUnknown PTR PTR"

                      ELSEIF wIndirectionLevel = 1 THEN

                         IF ((wFlags AND PARAMFLAG_FOUT) = PARAMFLAG_FOUT) OR ((wFlags AND PARAMFLAG_FRETVAL) = PARAMFLAG_FRETVAL) THEN

                            cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS IUnknown PTR PTR"

                         ELSE

                            cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS IUnknown PTR"

                         END IF

                      ELSE

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS IUnknown PTR"

                      END IF

                   CASE "VT_DISPATCH"

                      IF wIndirectionLevel = 2 THEN

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS IDispatch PTR PTR"

                      ELSEIF wIndirectionLevel = 1 THEN

                         IF ((wFlags AND PARAMFLAG_FOUT) = PARAMFLAG_FOUT) OR ((wFlags AND PARAMFLAG_FRETVAL) = PARAMFLAG_FRETVAL) THEN

                            cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS IDispatch PTR PTR"

                         ELSE

                            cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS IDispatch PTR"

                         END IF

                      ELSE

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS IDispatch PTR"

                      END IF

                   CASE "VT_VOID"

                      IF wIndirectionLevel = 2 THEN

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS ANY PTR PTR"

                      ELSEIF wIndirectionLevel = 1 THEN

                         IF ((wFlags AND PARAMFLAG_FOUT) = PARAMFLAG_FOUT) OR ((wFlags AND PARAMFLAG_FRETVAL) = PARAMFLAG_FRETVAL) THEN

                            cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS ANY PTR PTR"

                         ELSE

                            cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS ANY PTR"

                         END IF

                      ELSE

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS ANY PTR"

                      END IF

                   CASE "VT_LPSTR"

                      IF wIndirectionLevel = 2 THEN

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS ZSTRING PTR PTR"

                      ELSE

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS ZSTRING PTR"

                      END IF

                   CASE "VT_LPWSTR"

                      IF wIndirectionLevel = 2 THEN

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS WSTRING PTR PTR"

                      ELSE

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS WSTRING PTR"

                      END IF

                   CASE "VT_BSTR"

                      IF wIndirectionLevel = 2 THEN

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS BSTR PTR PTR"

                      ELSEIF wIndirectionLevel = 1 THEN

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS BSTR PTR"

                      ELSE

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName & " AS BSTR"

                      END IF

                   CASE ELSE

                      IF wIndirectionLevel = 2 THEN

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName &  " AS " & **cbstrFBKeyword & " PTR PTR"

                      ELSEIF wIndirectionLevel = 1 THEN

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName &  " AS " & **cbstrFBKeyword & " PTR"

                      ELSE

                         cbstrFBSyntax = "BYVAL " & **cbstrParamName &  " AS " & **cbstrFBKeyword

                      END IF

                END SELECT

             END IF

       END SELECT

       ' // See of it is an optional parameter without a default value

       IF (pParam[y].paramdesc.wParamFlags AND PARAMFLAG_FOPT) = PARAMFLAG_FOPT AND _

          (pParam[y].paramdesc.wParamFlags AND PARAMFLAG_FHASDEFAULT) <> PARAMFLAG_FHASDEFAULT THEN

          IF RIGHT(**cbstrFBSyntax, 4) = " PTR" THEN cbstrFBSyntax += " = NULL"

          IF RIGHT(**cbstrFBSyntax, 11) = " AS VARIANT" THEN cbstrFBSyntax += " = TYPE(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND)"

       END IF

       ' // See if it has a default value

       IF (pParam[y].paramdesc.wParamFlags AND PARAMFLAG_FHASDEFAULT) = PARAMFLAG_FHASDEFAULT THEN

          DIM pex AS PARAMDESCEX PTR = pParam[y].paramdesc.pparamdescex

          DIM cbsDefaultValue AS CBSTR = AfxVarToBstr(@pex->vardefaultvalue)

          IF pex->vardefaultvalue.vt = VT_BSTR THEN

             TreeView_AddItem(hTreeView, hParamNameNode, NULL, "Default value = " & CHR(34) & **cbsDefaultValue & CHR(34))

'               cbstrFBSyntax += " = " & CHR(34) & **cbsDefaultValue & CHR(34)

          ELSE

             TreeView_AddItem(hTreeView, hParamNameNode, NULL, "Default value = " & cbsDefaultValue)

             ' // Some typelibs have unprintable default values, e.g. wbemdisp.tlb,

             ' // that has unprintable IDispatch PTR values.

             IF LEN(cbsDefaultValue) THEN cbstrFBSyntax += " = " & cbsDefaultValue

          END IF

       END IF

       TreeView_AddItem(hTreeView, hParamNameNode, NULL, "FB syntax = " & cbstrFBSyntax)

       TreeView_Expand(hTreeView, hParamNameNode, TVE_EXPAND)

    NEXT

 END IF

 

 ' // Exand the parameters node

'   TreeView_Expand(hTreeView, hParamsNode, TVE_EXPAND)

 

 ' // DO NOT free the BSTRs; they are owned by the callee

 ' // Free the BSTRs of the array

'   FOR i AS LONG = LBOUND(rgbstrNames) TO UBOUND(rgbstrNames)

'      IF rgbstrNames(i) THEN SysFreeString(rgbstrNames(i))

'   NEXT

 

 ' // Just to satisfy the compiler rules; it has no useful meaning

 RETURN hr

 

END FUNCTION

' =====================================================================================