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

Interfaces

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

The type infos TKIND_INTERFACE and TKIND_DISPATCH provide information about the implemented interfaces and its methods and properties.

 

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

' Interfaces

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

CASE TKIND_INTERFACE, TKIND_DISPATCH

 cbstrName.Clear : cbstrHelpString.Clear

 hr = m_pTypeLib->GetDocumentation(i, @cbstrName, @cbstrHelpString, NULL, NULL)

 IF hr = S_OK THEN

    TreeView_AddItem hTreeView, m_hIIDsNode, NULL, "IID_" & cbstrName & " = " & CHR(34) & AfxGuidText(pTypeAttr->guid) & CHR(34)

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

    ' If it is a dual interface and the VTable option has been set, try to change the view.

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

    DIM VTableView AS BOOLEAN = m_VTableView

    IF pTKind = TKIND_DISPATCH AND (pTypeAttr->wTypeFlags AND TYPEFLAG_FDUAL) = TYPEFLAG_FDUAL THEN

       IF VTableView = TRUE THEN

          DO   ' // Fake DO LOOP to allow exit without GOTO

             ' // Attempt to change the view to VTable

             pRefType = NULL

             hr = pTypeInfo->GetRefTypeOfImplType(-1, @pRefType)

             IF hr <> S_OK OR pRefType = NULL THEN

                VTableView = FALSE

                EXIT DO

             END IF

             hr = pTypeInfo->GetRefTypeInfo(pRefType, @pRefTypeInfo)

             IF hr <> S_OK OR pRefTypeInfo = NULL THEN

                VTableView = FALSE

                EXIT DO

             END IF

             pRefTypeAttr = NULL

             hr = pRefTypeInfo->GetTypeAttr(@pRefTypeAttr)

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

             IF AfxGuidText(pRefTypeAttr->guid) <> "{00000000-0000-0000-0000-000000000000}" THEN

                TreeView_AddItem(hTreeView, hSubNode, NULL, "IID: " & AfxGuidText(pRefTypeAttr->guid))

             END IF

             IF LEN(cbstrHelpString) THEN TreeView_AddItem(hTreeView, hSubNode, NULL, "Documentation string: " & cbstrHelpString)

             IF pRefTypeAttr->wTypeFlags THEN TreeView_AddItem(hTreeView, hSubNode, NULL, "Attributes =  " & WSTR(pRefTypeAttr->wTypeFlags) & " [&h" & HEX(pRefTypeAttr->wTypeFlags, 8) & "]" & TLB_InterfaceFlagsToStr(pRefTypeAttr->wTypeFlags))

             cbstrInheritedInterface = TLB_GetImplementedInterface(pRefTypeInfo)

             TreeView_AddItem(hTreeView, hSubNode, NULL, "Inherited interface = " & cbstrInheritedInterface)

             ' /*** Datamembers ***/

             IF pRefTypeAttr->cVars THEN

                hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, "Number of datamembers = " & WSTR(pRefTypeAttr->cVars))

                this.GetMembers (pRefTypeInfo, pRefTypeAttr, hTreeView, hSubNode2)

             END IF

             ' /*** Retrieves the methods and properties ***/

             IF @pRefTypeAttr->cFuncs THEN

                hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, "Number of methods = " & WSTR(pRefTypeAttr->cFuncs))

                this.GetFunctions(pRefTypeInfo, pREfTypeAttr, hTreeView, hSubNode2, VTableView, TRUE, pTKind, cbstrImplInterface)

             ELSE

                hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, "Number of methods = 0")

             END IF

             IF pRefTypeInfo THEN

                IF pTypeAttr THEN pRefTypeInfo->ReleaseTypeAttr(pRefTypeAttr)

                pRefTypeInfo->Release

             END IF

             ' // exit the fake loop

             EXIT DO

          LOOP

       END IF

    ELSE

       VTableView = FALSE

    END IF

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

    ' ...else use the default view

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

    IF pTKind = TKIND_INTERFACE OR pTKind = TKIND_DISPATCH AND CLNG(VTableView) = FALSE THEN

       cbstrImplInterface = TLB_GetImplementedInterface(pTypeInfo)

       IF cbstrImplInterface <> "" THEN

          IF UCASE(cbstrImplInterface) <> "IUNKNOWN" AND UCASE(cbstrImplInterface) <> "IDISPATCH" THEN

             cbstrImplInterface = TLB_GetBaseClass(m_pTypeLib, cbstrName)

          END IF

       END IF

       IF pTKind = TKIND_INTERFACE THEN

          IF UCASE(cbstrImplInterface) = "IUNKNOWN" AND (pTypeAttr->wTypeFlags AND TYPEFLAG_FOLEAUTOMATION) = TYPEFLAG_FOLEAUTOMATION THEN

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

          ELSEIF UCASE(cbstrImplInterface) = "IDISPATCH" AND (pTypeAttr->wTypeFlags AND TYPEFLAG_FDUAL) <> TYPEFLAG_FDUAL THEN

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

          ELSE

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

          END IF

       ELSEIF pTKind = TKIND_DISPATCH THEN

          IF (pTypeAttr->wTypeFlags AND TYPEFLAG_FDUAL) = TYPEFLAG_FDUAL THEN

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

          ELSEIF INSTR(cwsEvents, "#" & cbstrName & "#") THEN

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

          ELSE

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

          END IF

       END IF

       IF AfxGuidText(pTypeAttr->guid) <> "{00000000-0000-0000-0000-000000000000}" THEN

          TreeView_AddItem(hTreeView, hSubNode, NULL, "IID: " & AfxGuidText(pTypeAttr->guid))

       END IF

       IF LEN(cbstrHelpString) THEN TreeView_AddItem(hTreeView, hSubNode, NULL, "Documentation string: " & cbstrHelpString)

       IF pTypeAttr->wTypeFlags THEN TreeView_AddItem(hTreeView, hSubNode, NULL, "Attributes =  " & WSTR(pTypeAttr->wTypeFlags) & " [&h" & HEX(pTypeAttr->wTypeFlags, 8) & "]" & TLB_InterfaceFlagsToStr(pTypeAttr->wTypeFlags))

       IF LEN(cbstrImplInterface) THEN TreeView_AddItem(hTreeView, hSubNode, NULL, "Inherited interface = " & cbstrImplInterface)

       ' /*** Datamembers ***/

       IF pTypeAttr->cVars THEN

          hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, "Number of datamembers = " & WSTR(pTypeAttr->cVars))

          this.GetMembers (pTypeInfo, pTypeAttr, hTreeView, hSubNode2)

       END IF

       ' /*** Retrieves the methods and properties ***/

       IF pTypeAttr->cFuncs THEN

          hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, "Number of methods = " & WSTR(pTypeAttr->cFuncs))

          IF pTKind = TKIND_INTERFACE THEN

             this.GetFunctions(pTypeInfo, pTypeAttr, hTreeView, hSubNode2, TRUE, TRUE, pTKind, cbstrImplInterface)

          ELSE

             this.GetFunctions(pTypeInfo, pTypeAttr, hTreeView, hSubNode2, VTableView, TRUE, pTKind, cbstrImplInterface)

          END IF

       ELSE

          hSubNode2 = TreeView_AddItem(hTreeView, hSubNode, NULL, "Number of methods = 0")

       END IF

    END IF

 END IF

 

A very important particularity is that the information can be returned in two different kind of views, the VTable view and the Automation view, aka Visual Basic view, that it is the default (after all, Automation was designed by te VB team).

 

To change the type of views from the default Automation one to the VTable one, we have to call the GetRefTypeOfImplType of the ITypeInfo interface. The meager documentation provided by Microsoft states that "If a type description describes a COM class, it retrieves the type description of the implemented interface types. For an interface, GetRefTypeOfImplType returns the type information for inherited interfaces, if any exist." See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms221569(v=vs.85).aspx

 

This doesn't help much, does it? Fortunately, there is a remark at the bottom: "If the TKIND_DISPATCH type description is for a dual interface, the TKIND_INTERFACE type description can be obtained by calling GetRefTypeOfImplType with an indexof –1, and by passing the returned pRefTypehandle to GetRefTypeInfo to retrieve the type information."

 

So, if we have a TKIND_DISPATCH description and be want a TKIND_INTERFACE description (assuming that the Dispatch interface is dual and not a dispatch only interface), we can get it passing -1 to GetRefTypeOfImplType.

 

' // Attempt to change the view to VTable

pRefType = NULL

hr = pTypeInfo->GetRefTypeOfImplType(-1, @pRefType)

IF hr <> S_OK OR pRefType = NULL THEN

 VTableView = FALSE

 EXIT DO

END IF

hr = pTypeInfo->GetRefTypeInfo(pRefType, @pRefTypeInfo)

IF hr <> S_OK OR pRefTypeInfo = NULL THEN

 VTableView = FALSE

 EXIT DO

END IF

pRefTypeAttr = NULL

hr = pRefTypeInfo->GetTypeAttr(@pRefTypeAttr)