2010-07-10 2 views
0

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

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

Я ценю любое понимание.

ответ

1

Волшебное 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; 
    } 
} 
Смежные вопросы