Доступ к ISimpleDOMNode в Mozilla с помощью IAccessible - PullRequest
0 голосов
/ 10 июля 2010

У меня есть следующий код:

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 возвращает «Неверный параметр».Я видел другие предложения, одно из которых не использует QueryService - просто вызывал QueryInterface с IID_ISimpleDom * - но эти вызовы возвращают ошибку «Нет службы».

Я также видел предложения по переходу к документуобъект и получить ссылку на узел оттуда - но я не совсем уверен, как это сделать (я новичок в IAccessibility).

Я ценю любую проницательность.

1 Ответ

1 голос
/ 12 марта 2011

Magic 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 и получением провайдера, вам может понадобиться перемещаться по доступной иерархии, которая может быть немного запутанной.

Посмотрите на этот код проекта - 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;
    }
}
...