Implementieren von IAccessibleEx für Anbieter
In diesem Abschnitt wird erläutert, wie Sie Microsoft Benutzeroberflächenautomatisierung-Anbieterfunktionen zu einem Microsoft Active Accessibility-Server hinzufügen, indem Sie die IAccessibleEx-Schnittstelle implementieren.
Berücksichtigen Sie vor der Implementierung von IAccessibleEx die folgenden Anforderungen:
- Die grundlegende Objekthierarchie für barrierefreie Microsoft Active Accessibility muss sauber sein. IAccessibleEx kann Probleme mit vorhandenen barrierefreien Objekthierarchien nicht beheben. Alle Probleme mit der Objektmodellstruktur müssen in der Microsoft Active Accessibility-Implementierung behoben werden, bevor IAccessibleEx implementiert wird.
- Die IAccessibleEx-Implementierung muss sowohl der Microsoft Active Accessibility-Spezifikation als auch der Benutzeroberflächenautomatisierung-Spezifikation entsprechen. Es stehen Tools zur Verfügung, um die Konformität nach beiden Spezifikationen zu überprüfen. Weitere Informationen finden Sie unter Testtools und Benutzeroberflächenautomatisierung Verify (UIA Verify) Test Automation Framework.
Die Implementierung von IAccessibleEx erfordert die folgenden Standard Schritte:
- Implementieren Sie IServiceProvider für das barrierefreie Objekt, damit die IAccessibleEx-Schnittstelle in diesem oder einem separaten Objekt gefunden werden kann.
- Implementieren Sie IAccessibleEx für das barrierefreie Objekt.
- Erstellen Sie barrierefreie Objekte für alle untergeordneten Microsoft Active Accessibility-Elemente, die in Microsoft Active Accessibility durch die IAccessible-Schnittstelle des übergeordneten Objekts dargestellt werden (z. B. Listenelemente). Implementieren Sie IAccessibleEx für diese Objekte.
- Implementieren Sie IRawElementProviderSimple für alle zugänglichen Objekte.
- Implementieren Sie die entsprechenden Steuerelementmusterschnittstellen für die zugänglichen Objekte.
Implementieren der IServiceProvider-Schnittstelle
Da sich die Implementierung von IAccessibleEx für ein Steuerelement möglicherweise in einem separaten Objekt befindet, können Clientanwendungen sich nicht auf QueryInterface verlassen, um diese Schnittstelle abzurufen. Stattdessen wird erwartet, dass Clients IServiceProvider::QueryService aufrufen. In der folgenden Beispielimplementierung dieser Methode wird davon ausgegangen, dass IAccessibleEx nicht für ein separates Objekt implementiert ist. Daher ruft die -Methode einfach bis QueryInterface auf.
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;
}
};
Implementieren der IAccessibleEx-Schnittstelle
In Microsoft Active Accessibility wird ein Benutzeroberflächenelement immer durch eine IAccessible-Schnittstelle und eine untergeordnete ID identifiziert. Ein einzelner instance von IAccessible kann mehrere UI-Elemente darstellen.
Da jedes IAccessibleEx-instance nur ein einzelnes UI-Element darstellt, muss jedes IAccessible-Paar und jedes untergeordnete ID-Paar einem einzelnen IAccessibleEx-instance zugeordnet werden. IAccessibleEx enthält zwei Methoden für die Verarbeitung dieser Zuordnung:
- GetObjectForChild: Ruft die IAccessibleEx-Schnittstelle für das angegebene untergeordnete Element ab. Diese Methode gibt NULL zurück, wenn die IAccessibleEx-Implementierung die angegebene untergeordnete ID nicht erkennt, keine IAccessibleEx für das angegebene untergeordnete Element aufweist oder ein untergeordnetes Element darstellt.
- GetIAccessiblePair: Ruft die IAccessible-Schnittstelle und die untergeordnete ID für das IAccessibleEx-Element ab. Für IAccessible-Implementierungen , die keine untergeordnete ID verwenden, ruft diese Methode das entsprechende IAccessible-Objekt und CHILDID_SELF ab.
Das folgende Beispiel zeigt die Implementierung der Methoden GetObjectForChild und GetIAccessiblePair für ein Element in einer benutzerdefinierten Listenansicht. Die Methoden ermöglichen es Benutzeroberflächenautomatisierung, das IAccessible- und das untergeordnete ID-Paar einem entsprechenden IAccessibleEx-instance zuzuordnen.
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;
}
}
Wenn eine barrierefreie Objektimplementierung keine untergeordnete ID verwendet, können die Methoden dennoch implementiert werden, wie im folgenden Codeausschnitt gezeigt.
// 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;
}
Implementieren der IRawElementProviderSimple-Schnittstelle
Server verwenden IRawElementProviderSimple, um Informationen zu Benutzeroberflächenautomatisierung Eigenschaften und Steuerelementmustern verfügbar zu machen. IRawElementProviderSimple umfasst die folgenden Methoden:
- GetPatternProvider: Diese Methode wird verwendet, um Steuerelementmusterschnittstellen verfügbar zu machen. Es gibt ein Objekt zurück, das das angegebene Steuerelementmuster unterstützt, oder NULL , wenn das Steuerelementmuster nicht unterstützt wird.
- GetPropertyValue: Diese Methode wird verwendet, um Benutzeroberflächenautomatisierung Eigenschaftswerte verfügbar zu machen.
- HostRawElementProvider: Diese Methode wird nicht mit IAccessibleEx-Implementierungen verwendet.
- ProviderOptions: Diese Methode wird nicht mit IAccessibleEx-Implementierungen verwendet.
Ein IAccessibleEx-Server macht Steuerelementmuster verfügbar, indem IRawElementProviderSimple::GetPatternProvider implementiert wird. Diese Methode verwendet einen ganzzahligen Parameter, der das Steuerelementmuster angibt. Der Server gibt NULL zurück, wenn das Muster nicht unterstützt wird. Wenn die Steuerelementmusterschnittstelle unterstützt wird, geben Server ein IUnknown zurück, und der Client ruft dann QueryInterface auf, um das entsprechende Steuerelementmuster abzurufen.
Ein IAccessibleEx-Server kann Benutzeroberflächenautomatisierung Eigenschaften (z. B. LabeledBy und IsRequiredForForm) unterstützen, indem IRawElementProviderSimple::GetPropertyValue implementiert und eine ganze Zahl PROPERTYID angegeben wird, die die Eigenschaft als Parameter identifiziert. Diese Technik gilt nur für Benutzeroberflächenautomatisierung Eigenschaften, die nicht in einer Steuerelementmusterschnittstelle enthalten sind. Eigenschaften, die einer Steuerelementmusterschnittstelle zugeordnet sind, werden über die Steuerelementmusterschnittstellenmethode verfügbar gemacht. Beispielsweise würde die IsSelected-Eigenschaft aus dem SelectionItem-Steuerelementmuster mit ISelectionItemProvider::get_IsSelected verfügbar gemacht.