Поделиться через


Реализация IAccessibleEx для поставщиков

В этом разделе объясняется, как добавить возможности поставщика microsoft модель автоматизации пользовательского интерфейса на сервер Microsoft Active Accessibility, реализуя интерфейс IAccessibleEx.

Перед реализацией IAccessibleEx рассмотрите следующие требования:

Реализация IAccessibleEx требует выполнения следующих основных действий.

  • Реализуйте IServiceProvider в объекте со специальными возможностями, чтобы интерфейс IAccessibleEx можно было найти в этом или отдельном объекте.
  • Реализуйте IAccessibleEx в объекте со специальными возможностями.
  • Создайте объекты со специальными возможностями для всех дочерних элементов Microsoft Active Accessibility, которые в Microsoft Active Accessibility представлены интерфейсом IAccessible в родительском объекте (например, элементы списка). Реализуйте IAccessibleEx для этих объектов.
  • Реализуйте IRawElementProviderSimple для всех доступных объектов.
  • Реализуйте соответствующие интерфейсы шаблонов управления на доступных объектах.

Реализация интерфейса IServiceProvider

Так как реализация IAccessibleEx для элемента управления может находиться в отдельном объекте, клиентские приложения не могут полагаться на QueryInterface для получения этого интерфейса. Вместо этого клиенты должны вызывать IServiceProvider::QueryService. В следующем примере реализации этого метода предполагается, что IAccessibleEx не реализован в отдельном объекте, поэтому метод просто вызывает запросInterface.

           
HRESULT CListboxAccessibleObject::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
{
    if (ppvObject == NULL)
    {
        return E_INVALIDARG;
    }
    *ppvObject = NULL;
    if (guidService == __uuidof(IAccessibleEx))
    {
        return QueryInterface(riid, ppvObject);
    }
    else 
    {
        return E_NOINTERFACE;
    }
};      

Реализация интерфейса IAccessibleEx

В Microsoft Active Accessibility элемент пользовательского интерфейса всегда определяется интерфейсом IAccessible и дочерним идентификатором. Один экземпляр IAccessible может представлять несколько элементов пользовательского интерфейса.

Так как каждый экземпляр IAccessibleEx представляет только один элемент пользовательского интерфейса, каждая пара идентификаторов IAccessible и дочернего идентификатора должна быть сопоставлена с одним экземпляром IAccessibleEx. IAccessibleEx включает два метода для обработки этого сопоставления:

  • GetObjectForChild — извлекает интерфейс IAccessibleEx для указанного дочернего элемента. Этот метод возвращает значение NULL , если реализация IAccessibleEx не распознает указанный дочерний идентификатор, не имеет IAccessibleEx для указанного дочернего элемента или представляет дочерний элемент.
  • GetIAccessiblePair — извлекает интерфейс IAccessible и дочерний идентификатор элемента IAccessibleEx. Для реализаций IAccessible, которые не используют дочерний идентификатор, этот метод извлекает соответствующий объект IAccessible и CHILDID_SELF.

В следующем примере показана реализация методов GetObjectForChild и GetIAccessiblePair для элемента в пользовательском представлении списка. Методы позволяют модель автоматизации пользовательского интерфейса сопоставлять пару идентификаторов IAccessible и дочернего идентификатора с соответствующим экземпляром IAccessibleEx.

           
HRESULT CListboxAccessibleObject::GetObjectForChild(
    long idChild, IAccessibleEx **ppRetVal)
{ 
    VARIANT vChild;
    vChild.vt = VT_I4;
    vChild.lVal = idChild;
    HRESULT hr = ValidateChildId(vChild);
    if (FAILED(hr))
    {
        return E_INVALIDARG;
    }
    // List item accessible objects are stored as an array of
    // pointers; for the purpose of this example it is assumed that 
    // the list contents will not change. Accessible objects are
    // created only when needed.
    if (itemProviders[idChild - 1] == NULL)
    {
        // Create an object that supports UI Automation and
        // IAccessibleEx for the item.
        itemProviders[idChild - 1] = 
          new CListItemAccessibleObject(idChild, 
          g_pListboxControl);
        if (itemProviders[idChild - 1] == NULL)
        {
            return E_OUTOFMEMORY;
        }
    }
    IAccessibleEx* pAccEx = static_cast<IAccessibleEx*>
      (itemProviders[idChild - 1]);
    if (pAccEx != NULL)
    {
      pAccEx->AddRef();
    }
    *ppRetVal = pAccEx;
    return S_OK; 
}

HRESULT CListItemAccessibleObject::GetIAccessiblePair(
    IAccessible **ppAcc, long *pidChild)
{ 
    if (ppAcc == NULL || pidChild == NULL)
    {
        return E_INVALIDARG;   
    }

                CListboxAccessibleObject* pParent = 
        m_control->GetAccessibleObject();

    HRESULT hr = pParent->QueryInterface( 
        __uuidof(IAccessible), (void**)ppAcc);
    if (FAILED(hr))
    {
        *pidChild = 0;
        return E_NOINTERFACE;
    }
    *pidChild = m_childID; 
    return S_OK; 
}
}

Если реализация доступного объекта не использует дочерний идентификатор, методы по-прежнему можно реализовать, как показано в следующем фрагменте кода.

           

    // This sample implements IAccessibleEx on the same object; it could use a tear-off
    // or inner object instead.
    class MyAccessibleImpl: public IAccessible,
                        public IAccessibleEx,
                        public IRawElementProviderSimple
    {
    public:
    ...
   HRESULT STDMETHODCALLTYPE GetObjectForChild( long idChild, IAccessibleEx **ppRetVal )
    {
        // This implementation does not support child IDs.
        *ppRetVal = NULL;
        return S_OK;
    }

    HRESULT STDMETHODCALLTYPE GetIAccessiblePair( IAccessible ** ppAcc, long * pidChild )
    {
        // This implementation assumes that IAccessibleEx is implemented on same object as
        // IAccessible.
        *ppAcc = static_cast<IAccessible *>(this);
        (*ppAcc)->AddRef();
        *pidChild = CHILDID_SELF;
        return S_OK;
    }

Реализация интерфейса IRawElementProviderSimple

Серверы используют IRawElementProviderSimple для предоставления сведений о модель автоматизации пользовательского интерфейса свойствах и шаблонах элементов управления. IRawElementProviderSimple включает следующие методы:

  • GetPatternProvider— этот метод используется для предоставления интерфейсов шаблонов управления. Он возвращает объект, поддерживающий указанный шаблон элемента управления, или NULL , если шаблон элемента управления не поддерживается.
  • GetPropertyValue— этот метод используется для предоставления модель автоматизации пользовательского интерфейса значений свойств.
  • HostRawElementProvider— этот метод не используется с реализацией IAccessibleEx .
  • ProviderOptions— этот метод не используется с реализациями IAccessibleEx .

Сервер IAccessibleEx предоставляет шаблоны управления путем реализации IRawElementProviderSimple::GetPatternProvider. Этот метод принимает целочисленный параметр, указывающий шаблон элемента управления. Сервер возвращает значение NULL , если шаблон не поддерживается. Если интерфейс шаблона элемента управления поддерживается, серверы возвращают IUnknown , а клиент вызывает QueryInterface , чтобы получить соответствующий шаблон элемента управления.

Сервер IAccessibleEx может поддерживать свойства модель автоматизации пользовательского интерфейса (например, LabeledBy и IsRequiredForForm), реализуя IRawElementProviderSimple::GetPropertyValue и указав целочисленный PROPERTYID, определяющий свойство как параметр. Этот метод применяется только к свойствам модель автоматизации пользовательского интерфейса, которые не включены в интерфейс шаблона элемента управления. Свойства, связанные с интерфейсом шаблона элемента управления, предоставляются с помощью метода интерфейса шаблона элемента управления. Например, свойство IsSelected из шаблона элемента управления SelectionItem будет предоставлено с помощью ISelectionItemProvider::get_IsSelected.