c++ - 使用 IAccessible 访问 Mozilla 的 ISimpleDOMNode

标签 c++ firefox mozilla iaccessible

我有以下代码:

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 都成功并返回非 NULL 对象;但是,QueryService 返回“无效参数”。我看过其他建议,其中之一是不使用 QueryService - 只是用 IID_ISimpleDom* 调用 QueryInterface - 但这些调用返回“无服务”错误。

我还看到了导航到 Document 对象并从那里获取对节点的引用的建议 - 但我不太确定如何完成该操作(我是 IAccessibility 的新手)。

我很感激任何见解。

最佳答案

魔术 GUID 由 Mozilla 提供

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 智能指针和一些错误修复(或引入 ;))

//-----------------------------------------------------------------------------
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;
    }
}

关于c++ - 使用 IAccessible 访问 Mozilla 的 ISimpleDOMNode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3217470/

相关文章:

c++ - 我如何使用 lldb 和 VSCode 将调试器与 bitcoind 和 bitcoin-cli 一起使用?

javascript - webkit mozilla 动画的 css 回调

JavaScript:为什么 FileReader.onload 在 mozilla 中没有被调用?

javascript - 为什么 anime.js 不为 Firefox 或 Microsoft Edge 中的左侧属性设置动画?

javascript - 是否可以本地扩展 Web API 以允许 CSSRule.cssText 返回非标准 css 属性

c++ - 为什么使用 `nullptr` 会导致性能下降 [在 LeetCode 上]?

c++ - 如何在我的主程序 C++ 中使用我自己制作的数组头文件?

c++ - 保持对同一实例 C++ 的引用

jquery - $ ("form").submit(function() { 在 Firefox 中不起作用

android - 如何以非编程方式在 Android 上配置代理排除列表?