# ComObjQuery

查询 COM 对象的接口或服务.

    InterfacePointer := ComObjQuery(ComObj, SID, IID)

## 参数

ComObj

  类型: ComValue, 对象, 或整数

  COM 包装器对象, 接口指针或一个具有 `Ptr` 属性的对象, 该属性返回一个接口指针.

IID

  类型: 字符串

  格式为 "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" 的接口标识符(GUID).

SID

  类型: 字符串

  与 IID 格式相同的服务标识符. 省略此参数时, 还要省略逗号.

## 返回值

类型: ComValue

If the interface is supported, 该函数返回一个 variant type 为 VT_UNKNOWN(13) 的 COM 封装对象.

## Error Handling

An exception is thrown on failure.

## 备注

在此函数使用两个参数时, 它相当于 IUnknown::QueryInterface. 如果同时指定了 SID 和 IID, 那么它会内部查询 IServiceProvider 接口, 然后调用 IServiceProvider::QueryService.

ComCall 可以用来调用原生接口方法.

## 相关

ComCall, ComObject, ComObjGet, ComObjActive

## 示例

确定对象的类名.

    obj := ComObject("Scripting.Dictionary")

    MsgBox "Interface name: " ComObjType(obj, "name")

    IID_IProvideClassInfo := "{B196B283-BAB4-101A-B69C-00AA00341D07}"

    ; 请求对象的 IProvideClassInfo 接口.
    try
        pci := ComObjQuery(obj, IID_IProvideClassInfo)
    catch
    {
        MsgBox "IProvideClassInfo interface not supported."
        return
    }

    ; 调用 GetClassInfo 来获取 ITypeInfo 接口的指针.
    ComCall(3, pci, "ptr*", &ti := 0)

    ; 封装 ti 以确保自动清理.
    ti := ComValue(13, ti)

    ; 调用 GetDocumentation 来获取对象的完整类型名称.
    ComCall(12, ti, "int", -1, "ptr*", &pname := 0, "ptr", 0, "ptr", 0, "ptr", 0)

    ; 转换 BSTR 指针为可用的字符串.
    name := StrGet(pname, "UTF-16")

    ; 清理.
    DllCall("oleaut32\SysFreeString", "ptr", pname)
    pci := ti := ""

    ; 显示类型名称!
    MsgBox "Class name: " name

自动化现有的 Internet Explorer 窗口.

    sURL := "https://www.autohotkey.com/boards/"
    if WebBrowser := GetWebBrowser()
        WebBrowser.Navigate(sURL)

    GetWebBrowser()
    {
        ; 获取指向顶部 IE 窗口的文档对象的原始指针.
        static msg := DllCall("RegisterWindowMessage", "Str", "WM_HTML_GETOBJECT")
        lResult := SendMessage(msg, 0, 0, "Internet Explorer_Server1", "ahk_class IEFrame")
        if !lResult
            return  ; 未找到 IE.
        static IID_IHTMLDocument2 := GUID("{332C4425-26CB-11D0-B483-00C04FD90119}")
        static VT_UNKNOWN := 13
        DllCall("oleacc\ObjectFromLresult", "Ptr", lResult
            , "Ptr", IID_IHTMLDocument2, "Ptr", 0
            , "Ptr*", pdoc := ComValue(VT_UNKNOWN, 0))

        ; 查询 WebBrowserApp 服务. 在这种特殊情况中,
        ; SID 和 IID 相同, 但不总是如此.
        static IID_IWebBrowserApp := "{0002DF05-0000-0000-C000-000000000046}"
        static SID_SWebBrowserApp := IID_IWebBrowserApp
        pweb := ComObjQuery(pdoc, SID_SWebBrowserApp, IID_IWebBrowserApp)

        ; 为了便于使用, 将 WebBrowser 对象返回为 IDispatch.
        ; 这只是因为 IWebBrowserApp 是由 IDispatch 派生出来的.
        ; pweb 会自动释放它的 ptr, 所以用 AddRef 来计数.
        ObjAddRef(pweb.ptr)
        static VT_DISPATCH := 9
        return ComValue(VT_DISPATCH, pweb.ptr)
    }

    GUID(sGUID) ; 转换字符串为二进制的 GUID 并返回其缓冲.
    {
        GUID := Buffer(16, 0)
        if DllCall("ole32\CLSIDFromString", "WStr", sGUID, "Ptr", GUID) < 0
            throw ValueError("Invalid parameter #1", -1, sGUID)
        return GUID
    }

dftg