Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе объясняется, как добавить возможности поставщика службы автоматизации пользовательского интерфейса Майкрософт на сервер Microsoft Active Accessibility, реализуя интерфейс IAccessibleEx.
Перед реализацией IAccessibleExрассмотрите следующие требования:
- Базовая иерархия объектов доступности Microsoft Active Accessibility должна быть чистой. IAccessibleEx не может исправить проблемы с существующими иерархиями объектов со специальными возможностями. Все проблемы со структурой объектной модели должны быть исправлены в реализации Microsoft Active Accessibility перед реализацией IAccessibleEx.
- Реализация IAccessibleEx должна соответствовать спецификации Microsoft Active Accessibility и спецификации автоматизации пользовательского интерфейса. Средства доступны для проверки соответствия в обоих спецификациях. Дополнительные сведения см. в разделе Тестирование на доступность и тестовая платформа 'UI Automation Verify (UIA Verify)' для автоматизации тестирования.
Для реализации IAccessibleEx требуются следующие основные действия:
- Реализуйте IServiceProvider на доступном объекте, чтобы интерфейс IAccessibleEx мог быть найден на этом или отдельном объекте.
- Реализуйте IAccessibleEx на доступном объекте.
- Создание доступных объектов для всех дочерних элементов Microsoft Active Accessibility, которые в Microsoft Active Accessibility представлены интерфейсом IAccessible в родительском объекте (например, элементы списка). Реализуйте IAccessibleEx на этих объектах.
- Реализуйте IRawElementProviderSimple для всех доступных объектов.
- Реализуйте соответствующие интерфейсы шаблонов управления на доступных объектах.
Реализация интерфейса IServiceProvider
Так как реализация IAccessibleEx для элемента управления может находиться в отдельном объекте, клиентские приложения не могут полагаться на QueryInterface для получения этого интерфейса. Вместо этого клиенты должны вызывать IServiceProvider::QueryService. В следующем примере реализации этого метода предполагается, что IAccessibleEx не реализованы в отдельном объекте; поэтому метод просто вызывает QueryInterface.
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и пара Child ID должны быть сопоставлены с одним экземпляром 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.