首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用IAccessible访问Mozilla的ISimpleDOMNode

用IAccessible访问Mozilla的ISimpleDOMNode
EN

Stack Overflow用户
提问于 2010-07-10 09:40:11
回答 1查看 2.6K关注 0票数 0

我有以下代码:

代码语言:javascript
复制
IAccessible *pAccessible = NULL;
IServiceProvider *pServProv = NULL; 
AccessibleObjectFromWindow((HWND)0x0025093A, OBJID_CLIENT, IID_IAccessible, (void**)&pAccessible);

HRESULT hr = pAccessible->QueryInterface(IID_IServiceProvider, (void**)&pServProv);
if (SUCCEEDED(hr) && (pServProv != NULL))
{
    const GUID unused;
    ISimpleDOMDocument *pAccDoc = NULL;

    hr = pServProv->QueryService(unused, IID_ISimpleDOMDocument, (void**)&pAccDoc);

    if (SUCCEEDED(hr) && (pAccDoc != NULL))
    {
        // Success
    }
    else
    {
        // Failure
    }
}

上面的硬编码HWND是MozillaContentWindowClass的一个实例。

只要QueryService - AccessibleObjectFromWindow和QueryInterface都成功并返回非空对象,我就可以得到;但是,QueryService返回'Invalid Parameter‘。我还看到过其他建议,其中之一是不使用QueryService --只需使用IID_ISimpleDom*调用QueryInterface --但这些调用返回一个“No Service”错误。

我还看到了导航到Document对象并从中获取对节点的引用的建议-但我不太确定如何实现这一点(我是IAccessibility新手)。

我很感谢你的见解。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-03-12 14:34:14

Mozilla提供的魔术GUID

代码语言:javascript
复制
if (pAccChild)
{
    CComQIPtr<IServiceProvider> provider = pAccChild;
    if( provider ){
       const GUID refguid = {0x0c539790, 0x12e4, 0x11cf, 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8};

      CComPtr<ISimpleDOMNode> node;
      provider->QueryService(refguid, IID_ISimpleDOMNode, (void**)&node);
      CComQIPtr<ISimpleDOMDocument> ffdocument = node;
      if (node) {
        ffdocument->get_URL(&DOM_string);
        if (DOM_string != 0) { 
            addressbar = (const wchar_t *)_bstr_t(DOM_string, FALSE); 
        }
      }

现在,在AccessibleObjectFromWindow和获取提供者之间,您可能需要移动可访问的层次结构,这可能会有点混乱。

请查看此Code Project - XMSAALib以获取建议。

这里是一些树漫步的例子,涵盖了各种问题。从原始版本修改为使用ATL智能指针和一些错误修复(或引入;)

代码语言:javascript
复制
//-----------------------------------------------------------------------------
bool CXMSAALib::EnumAccessible(IAccessible *pIAccParent, IAccessibleEnumProc& lpEnumAccessibleProc )
{
    _ASSERTE(pIAccParent);

    // 2 ways to go through the children
    // * some parents will support the Enum(erator) interface where child ids may not be a contiguous sequence, and children may be returned as id or IAccessible directly
    // * others support the accChild function only where the count and ids should be contiguous.

    CComQIPtr<IEnumVARIANT> pEnum = pIAccParent;
    if( pEnum )
        pEnum->Reset();

    // get child count
    long nChildren = 0;
    if( FAILED( pIAccParent->get_accChildCount(&nChildren) ) )
        nChildren = 0;
    //TRACE(_T("nChildren=%d\n"), nChildren);

    bool bContinue = true;
    // skip 0 (self)
    for (long index = 1; (index <= nChildren) && bContinue; index++)
    {
        HRESULT hr =0;
        VARIANT varChildRef;
        VariantInit(&varChildRef);
        if (pEnum)
        {
            unsigned long nFetched = 0;
            hr = pEnum->Next(1, &varChildRef, &nFetched);
            //children may be returned as lVal id or IAccessible directly
            if (!SUCCEEDED(hr) || !nFetched )
            {
                bContinue = false;
                break;
            }
        }
        else
        {
            varChildRef.vt = VT_I4;
            varChildRef.lVal = index;
        }

        // IAccessible doesn't always allow indirect access to children that are also of type IAccessible
        // change the focus to the child element if we can
        VARIANT varChild;
        VariantInit(&varChild);
        CComPtr<IAccessible> pIAccChild;
        FocusOnChild( pIAccParent, varChildRef, pIAccChild, varChild );

        bContinue = lpEnumAccessibleProc(pIAccChild, varChild);

        if ( bContinue 
            && pIAccChild 
            && CHILDID_SELF == varChild.lVal )
        {

            bContinue = EnumAccessible(pIAccChild, lpEnumAccessibleProc);

        }

        VariantClear(&varChild);
    }

    return bContinue;
}

//-----------------------------------------------------------------------------
bool CXMSAALib::EnumAccessible(HWND hwnd, IAccessibleEnumProc& lpEnumAccessibleProc) 
{
    if (::IsWindow(hwnd))
    {
        CComPtr<IAccessible> pIAccParent;

        HRESULT hr = AccessibleObjectFromWindow(hwnd, OBJID_CLIENT, IID_IAccessible, (void**)&pIAccParent);
        if (SUCCEEDED(hr) && pIAccParent)
        {
            VARIANT varChild;
            VariantInit(&varChild);
            varChild.vt = VT_I4;
            varChild.lVal = CHILDID_SELF;
            if( lpEnumAccessibleProc(pIAccParent, varChild) ) {
                EnumAccessible(pIAccParent, lpEnumAccessibleProc, nLevel+1);
            }

            VariantClear(&varChild);
            return true;
        }
    }
    return false;
}

//-----------------------------------------------------------------------------
void CXMSAALib::FocusOnChild( IAccessible * pIAccParent, VARIANT &varChildRef, CComPtr<IAccessible> &pIAccChild, VARIANT &varChild ) 
{
    // get IDispatch interface for the child
    CComPtr<IDispatch> pDisp;
    if (varChildRef.vt == VT_I4)
    {
        pIAccParent->get_accChild(varChildRef, &pDisp);
    }
    else if (varChildRef.vt == VT_DISPATCH)
    {
        pDisp = varChildRef.pdispVal;
    }

    // get IAccessible interface for the child
    CComQIPtr<IAccessible> pCAcc(pDisp);

    if (pCAcc && pCAcc != pIAccParent )
    {
        VariantInit(&varChild);
        varChild.vt = VT_I4;
        varChild.lVal = CHILDID_SELF;
        pIAccChild = pCAcc;
    }
    else
    {
        pIAccChild = pIAccParent;
        varChild = varChildRef;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3217470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档