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

Retrieving the methods and properties

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

The cFuncs member of the TYPEATTR structure contains the number of methods and properties implemented in an interface and the GetFuncDesc method of the ITypeInfo interface retrieves the FUNCDESC structure that contains information about a specified function ( https://msdn.microsoft.com/en-us/library/windows/desktop/ms221425(v=vs.85).aspx ), as well as the return type.

 

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

' Retrieve information about the methods, properties and functions.

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

FUNCTION CParseTypeLib.GetFunctions (BYVAL pTypeInfo AS Afx_ITypeInfo PTR, BYVAL pTypeAttr AS TYPEATTR PTR, _

 BYVAL hTreeView AS HWND, BYVAL hSubNode AS HTREEITEM, BYVAL bVTableView AS BOOLEAN, BYVAL bIsMethod AS BOOLEAN = FALSE, _

 BYVAL pTKind AS TYPEKIND = -1, BYVAL pwszImplInterface AS WSTRING PTR = NULL) AS HRESULT

 

 DIM hr AS HRESULT                       ' // HRESULT

 DIM x AS LONG                           ' // Loop counter

 DIM hSubNode2 AS HTREEITEM              ' // Sub node handle

 DIM pFuncDesc AS FUNCDESC PTR           ' // Pointer to a FUNCDESC structure

 DIM cbstrName AS CBSTR                  ' // Name

 DIM cbstrHelpString AS CBSTR            ' // Help string

 DIM dwHelpContext AS DWORD              ' // Help context number

 DIM cbstrDllName AS CBSTR               ' // DLL name

 DIM cbstrEntryPoint AS CBSTR            ' // Entry point

 DIM wOrdinal AS WORD                    ' // Ordinal

 DIM pRefTypeInfo AS Afx_ITypeInfo PTR   ' // Referenced TypeInfo interface

 DIM pReturnTypeAttr AS TYPEATTR PTR     ' // Referenced TYPEATTR structure

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

 DIM ReturnTypeKind AS TYPEKIND          ' // Return value type kind

 DIM cbstrType AS CBSTR                  ' // Type

 

 IF pTypeInfo = NULL OR pTypeAttr = NULL THEN RETURN E_INVALIDARG

 

DIM cbOrigName AS CBSTR

 FOR x = 0 TO pTypeAttr->cFuncs - 1

    ' // Gets a reference to the FuncDesc structure

    hr = pTypeInfo->GetFuncDesc(x, @pFuncDesc)

    IF hr <> S_OK OR pFuncDesc = NULL THEN EXIT FOR

    ' // Retrieve the name

    cbstrName.Clear : cbstrHelpString.Clear

    pTypeInfo->GetDocumentation(pFuncDesc->memid, @cbstrName, @cbstrHelpString, @dwHelpContext, NULL)

    IF bIsMethod THEN

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

       ' Workaround for libraries that can have illegal method names.

       ' For example, TLBINF32.DLL has a property called GetTypeInfo.

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

       DIM vtOffset AS LONG

#ifdef __FB_64BIT__

       vtOffset = 48

#else

       vtOffset = 24

#endif

       IF UCASE$(cbstrName) = "QUERYINTERFACE" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"

       IF UCASE$(cbstrName) = "ADDREF" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"

       IF UCASE$(cbstrName) = "RELEASE" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"

       IF UCASE$(cbstrName) = "GETTYPEINFOCOUNT" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"

       IF UCASE$(cbstrName) = "GETTYPEINFO" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"

       IF UCASE$(cbstrName) = "GETIDSOFNAMES" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"

       IF UCASE$(cbstrName) = "INVOKE" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"

       IF UCASE$(cbstrName) = "DELETE" THEN cbstrName += "_"

       IF UCASE$(cbstrName) = "PROPERTY" THEN cbstrName += "_"

 

       IF pTKind = TKIND_INTERFACE OR pTKind = TKIND_DISPATCH THEN

          IF pFuncDesc->invkind = INVOKE_FUNC THEN cbstrName = "METHOD " & cbstrName

          IF pFuncDesc->invkind = INVOKE_PROPERTYGET THEN cbstrName = "PROPERTY GET " & cbstrName

          IF pFuncDesc->invkind = INVOKE_PROPERTYPUT THEN cbstrName = "PROPERTY PUT " & cbstrName

          IF pFuncDesc->invkind = INVOKE_PROPERTYPUTREF THEN cbstrName = "PROPERTY PUTREF " & cbstrName

       END IF

       hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, cbstrName)

       TreeView_AddItem(hTreeView, hSubNode2, NULL, "VTable offset = " &  WSTR(pFuncdesc->oVft) & " [&h" & HEX(pFuncdesc->oVft, 8) & "]")

       TreeView_AddItem(hTreeView, hSubNode2, NULL, "DispID = " & WSTR(pFuncDesc->memid) & " [&h" & HEX(@pFuncDesc->memid, 8) & "]")

       IF LEN(cbstrHelpString) THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Help string = " & cbstrHelpString)

       IF dwHelpContext THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Help context = " & WSTR(dwHelpContext))

    ELSE

       IF pFuncDesc->elemdescFunc.tdesc.vt = VT_VOID THEN

          hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, "SUB " & cbstrName)

       ELSE

          hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, "FUNCTION " & cbstrName)

       END IF

       IF LEN(cbstrHelpString) THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Help string = " & cbstrHelpString)

       IF dwHelpContext THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Help context = " & WSTR(dwHelpContext))

       TreeView_AddItem(hTreeView, hSubNode2, NULL, "DispID = " & WSTR(pFuncDesc->memid) & " [&h" & HEX(pFuncDesc->memid, 8) & "]")

       cbstrDllName.Clear : cbstrEntryPoint.Clear

       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

    END IF

 

    ' // Kind of function

    SELECT CASE pFuncDesc->funckind

       CASE FUNC_VIRTUAL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "FuncKind = Virtual")

       CASE FUNC_PUREVIRTUAL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "FuncKind = Pure virtual")

       CASE FUNC_NONVIRTUAL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "FuncKind = Non virtual")

       CASE FUNC_STATIC

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "FuncKind = Static")

       CASE FUNC_DISPATCH

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "FuncKind = Dispatch")

    END SELECT

    ' // Invoke kind

    SELECT CASE pFuncDesc->invkind

       CASE INVOKE_FUNC

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "InvokeKind = Function")

       CASE INVOKE_PROPERTYGET

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "InvokeKind = Get property")

       CASE INVOKE_PROPERTYPUT

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "InvokeKind = Put property")

       CASE INVOKE_PROPERTYPUTREF

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "InvokeKind = PutRef property")

    END SELECT

    ' // Calling convention

    SELECT CASE pFuncDesc->callconv

       CASE CC_FASTCALL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "Calling convention = FASTCALL")

       CASE CC_CDECL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "Calling convention = CDECL")

       CASE CC_MACPASCAL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "Calling convention = MACPASCAL")

       CASE CC_STDCALL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "Calling convention = STDCALL")

       CASE CC_FPFASTCALL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "Calling convention = FPFASTCALL")

       CASE CC_SYSCALL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "Calling convention = SYSCALL")

       CASE CC_MPWCDECL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "Calling convention = MPWCDECL")

       CASE CC_MPWPASCAL

          TreeView_AddItem(hTreeView, hSubNode2, NULL, "Calling convention = MPWPASCAL")

    END SELECT

 

    ' // More general information

    IF pFuncDesc->cParamsOpt THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Number of optional variant parameters = " & WSTR(pFuncDesc->cParamsOpt))

    IF pFuncDesc->cScodes THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Count of permitted Return values = " & WSTR(pFuncDesc->cScodes))

    IF pFuncDesc->wFuncFlags THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Attributes = " & WSTR(pFuncDesc->wFuncFlags)& " [&h" & HEX(pFuncDesc->wFuncFlags, 8) & "]" & TLB_FuncFlagsToStr(pFuncDesc->wFuncFlags))

    ' // Return type

    ReturnTypeKind = -1  ' // Because the TYPEKIND enum starts at 0

    IF pFuncDesc->elemdescFunc.tdesc.vt = VT_USERDEFINED THEN

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

       hr = pTypeInfo->GetRefTypeInfo(pFuncDesc->elemdescFunc.tdesc.hreftype, @pRefTypeInfo)

       IF hr = S_OK AND pRefTypeInfo <> NULL THEN

          cbstrType.Clear

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

          hr = pRefTypeInfo->GetTypeAttr(@pReturnTypeAttr)

          IF hr = S_OK AND pReturnTypeAttr <> NULL THEN

             TreeView_AddItem(hTreeView, hSubNode2, NULL, "Return type typeKind = " & TLB_TypeKindToStr(pReturnTypeAttr->typekind))

             ReturnTypeKind = pReturnTypeAttr->typekind

             pRefTypeInfo->ReleaseTypeAttr(pReturnTypeAttr)

             pReturnTypeAttr = NULL

          END IF

          IF pRefTypeInfo THEN pRefTypeInfo->Release

       END IF

    ELSEIF pFuncDesc->elemdescFunc.tdesc.vt = VT_PTR THEN

       ' // Pointer to a TYPEDESC structure

       ptdesc = pFuncDesc->elemdescFunc.tdesc.lptdesc

       DO

          SELECT CASE ptdesc->vt

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

             CASE VT_PTR

                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

                   cbstrType.Clear

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

                   hr = pRefTypeInfo->GetTypeAttr(@pReturnTypeAttr)

                   IF hr = S_OK AND pReturnTypeAttr <> NULL THEN

                      TreeView_AddItem(hTreeView, hSubNode2, NULL, "Return type typeKind = " & TLB_TypeKindToStr(pReturnTypeAttr->typekind))

                      ReturnTypeKind = pReturnTypeAttr->typekind

                      pRefTypeInfo->ReleaseTypeAttr(pReturnTypeAttr)

                      pReturnTypeAttr = NULL

                   END IF

                   IF pRefTypeInfo THEN pRefTypeInfo->Release

                END IF

                EXIT DO

             CASE ELSE

                ' // Get the equivalent type

                cbstrType = TLB_VarTypeToConstant(ptdesc->vt)

                EXIT DO

          END SELECT

       LOOP

    ELSE

       ' // Get the equivalent type

       cbstrType = TLB_VarTypeToConstant(pFuncDesc->elemdescFunc.tdesc.vt)

    END IF

    ' // Return type

    TreeView_AddItem(hTreeView, hSubNode2, NULL, "Return type = " & cbstrType)

    DIM strReturn AS STRING = ""

    IF bVTableView = FALSE THEN

       IF ReturnTypeKind = TKIND_INTERFACE OR ReturnTypeKind = TKIND_DISPATCH THEN

          strReturn = "BYVAL rhs AS " & cbstrType & " PTR PTR"

       ELSEIF ReturnTypeKind = TKIND_ENUM THEN

          strReturn = "BYVAL rhs AS " & cbstrType & " PTR"

       ELSEIF ReturnTypeKind = TKIND_ALIAS THEN

          strReturn = "BYVAL rhs AS " & cbstrType & " PTR"

       ELSEIF pFuncDesc->elemdescFunc.tdesc.vt = VT_VOID THEN

          ' // With Automation view, VT_VOID means no return type

          strReturn = ""

       ELSEIF pFuncDesc->invkind <> INVOKE_PROPERTYGET AND pFuncDesc->cParams = 0 THEN

          ' // With Automation view, if it is not a get property and it has not

          ' // parameters, then it has not an OUT Return value but returns the value

          ' //  directly as the result of the method, e.g. AddRef and Release.

          strReturn = ""

       ELSE

          ' // Returns the value as an OUT parameter

          strReturn = "BYVAL rhs AS " & TLB_VarTypeToKeyword(pFuncDesc->elemdescFunc.tdesc.vt) & " PTR"

       END IF

       IF LEN(strReturn) THEN TreeView_AddItem(hTreeView, hSubNode2, NULL, "Return type FB syntax = " & strReturn)

    END IF

    ' // Parameters

    IF pFuncDesc->cParams THEN this.GetParameters(pTypeInfo, pFuncDesc, hTreeView, hSubNode2, bVTableView)

    ' // Expand the nodes

'      TreeView_Expand(hTreeView, hSubNode2, TVE_EXPAND)

    TreeView_Expand(hTreeView, hSubNode, TVE_EXPAND)

    ' // Release the FUNCDESC structure

    pTypeInfo->ReleaseFuncDesc(pFuncDesc)

    pFuncDesc = NULL

    ReturnTypeKind = -1

 NEXT

 

 IF pFuncDesc THEN pTypeInfo->ReleaseFuncDesc(pFuncDesc)

 

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

 FUNCTION = hr

 

END FUNCTION

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