Share via


Implementieren eines Server-Side Benutzeroberflächenautomatisierung-Anbieters

In diesem Thema wird beschrieben, wie Sie einen serverseitigen Microsoft Benutzeroberflächenautomatisierung-Anbieter für ein in C++ geschriebenes benutzerdefiniertes Steuerelement implementieren. Sie enthält die folgenden Abschnitte:

Codebeispiele, die das Implementieren serverseitiger Anbieter veranschaulichen, finden Sie unter How-To Topics for Benutzeroberflächenautomatisierung Providers( How-To Topics for Benutzeroberflächenautomatisierung Providers).

Struktur des Anbieters

Sie müssen einen UIA-Anbieter für jedes UI-Element implementieren, auf das ein UIA-Client zugreifen kann.

Beispielsweise muss jedes Element IRawElementProviderFragment implementieren, während das Stammelement der Anwendung IRawElementProviderFragmentRoot implementieren muss. Darüber hinaus sollte jedes Anbieterelement eine Verknüpfung mit einem:

  • parent
  • vorheriges Anbieterelement
  • next provider-Element
  • first provider child
  • Letztes untergeordnetes Anbieter

Anbieterschnittstellen

Die folgenden COM-Schnittstellen (Component Object Model) bieten Funktionen für benutzerdefinierte Steuerelemente. Um grundlegende Funktionen bereitzustellen, muss jeder Benutzeroberflächenautomatisierung Anbieter mindestens die IRawElementProviderSimple-Schnittstelle implementieren. Die Schnittstellen IRawElementProviderFragment und IRawElementProviderFragmentRoot sind optional, sollten jedoch für Elemente in einem komplexen Steuerelement implementiert werden, um zusätzliche Funktionen bereitzustellen.

Schnittstelle BESCHREIBUNG
Irawelementprovidersimple Stellt grundlegende Funktionen für ein Steuerelement bereit, das in einem Fenster gehostet wird, einschließlich Unterstützung für Steuerelementmuster und Eigenschaften.
IRawElementProviderFragment Fügt Funktionen für ein Element in einem komplexen Steuerelement hinzu, einschließlich navigation im Fragment, Festlegen des Fokus und Zurückgeben des umgebenden Rechtecks des Elements.
IRawElementProviderFragmentRoot Fügt Funktionen für das Stammelement in einem komplexen Steuerelement hinzu, einschließlich Suchen eines untergeordneten Elements an angegebenen Koordinaten und Festlegen des Fokuszustands für das gesamte Steuerelement.

 

Hinweis

In der Benutzeroberflächenautomatisierung-API für verwalteten Code bilden diese Schnittstellen eine Vererbungshierarchie. Dies ist in C++ nicht der Fall, wo die Schnittstellen vollständig getrennt sind.

 

Die folgenden Schnittstellen bieten zusätzliche Funktionen, die Implementierung ist jedoch optional.

Schnittstelle BESCHREIBUNG
IRawElementProviderAdviseEvents Ermöglicht dem Anbieter, Anforderungen für Ereignisse zu verfolgen.
IRawElementProviderHwndOverride Ermöglicht die Neupositionierung von fensterbasierten Elementen in der Benutzeroberflächenautomatisierung Struktur eines Fragments.

 

Erforderliche Funktionalität für Benutzeroberflächenautomatisierung-Anbieter

Für die Kommunikation mit Benutzeroberflächenautomatisierung muss Ihr Steuerelement die in der folgenden Tabelle beschriebenen Standard Funktionsbereiche implementieren.

Funktionalität Implementierung
Machen Sie den Anbieter für Benutzeroberflächenautomatisierung verfügbar. Geben Sie als Reaktion auf eine an das Steuerelementfenster gesendete WM_GETOBJECT Nachricht das Objekt zurück, das IRawElementProviderSimple implementiert. Für Fragmente muss dies der Anbieter für den Fragmentstamm sein.
Geben Sie Eigenschaftswerte an. Implementieren Sie IRawElementProviderSimple::GetPropertyValue , um Werte bereitzustellen oder zu überschreiben.
Aktivieren Sie den Client für die Interaktion mit dem Steuerelement. Implementieren Sie Schnittstellen, die jedes geeignete Steuerelementmuster unterstützen, z. B. IInvokeProvider. Geben Sie diese Steuerelementmusteranbieter in Ihrer Implementierung von IRawElementProviderSimple::GetPatternProvider zurück.
Auslösen von Ereignissen. UiaRaiseAutomationEvent, Methoden von IProxyProviderWinEventSink.
Aktivieren des Navigierens und Fokussierens in einem Fragment. Implementieren Sie IRawElementProviderFragment für jedes Element innerhalb des Fragments. Nicht erforderlich für Elemente, die nicht Teil eines Fragments sind.
Aktivieren sie das Fokussieren und Auffinden untergeordneter Elemente in einem Fragment. Implementieren Sie IRawElementProviderFragmentRoot. Nicht erforderlich für Elemente, die keine Fragmentwurzeln sind.

 

Eigenschaftswerte

Benutzeroberflächenautomatisierung Anbieter für benutzerdefinierte Steuerelemente müssen bestimmte Eigenschaften unterstützen, die von Benutzeroberflächenautomatisierung und Clientanwendungen verwendet werden können. Für Elemente, die in Fenstern gehostet werden, können Benutzeroberflächenautomatisierung einige Eigenschaften vom Standardfensteranbieter abrufen, müssen jedoch andere vom benutzerdefinierten Anbieter abrufen.

In der Regel müssen Anbieter für fensterbasierte Steuerelemente nicht die folgenden Eigenschaften bereitstellen, die durch PROPERTYID identifiziert werden:

Die RuntimeId-Eigenschaft eines einfachen Elements oder Fragmentstamms, das in einem Fenster gehostet wird, wird aus dem Fenster abgerufen. Fragmentelemente unter dem Stamm, z. B. Listenelemente in einem Listenfeld, müssen jedoch ihre eigenen Bezeichner bereitstellen. Weitere Informationen finden Sie unter IRawElementProviderFragment::GetRuntimeId.

Die IsKeyboardFocusable-Eigenschaft sollte für Anbieter zurückgegeben werden, die in einem Windows Forms-Steuerelement gehostet werden. In diesem Fall ist der Standardfensteranbieter möglicherweise nicht in der Lage, den richtigen Wert abzurufen.

Die Name-Eigenschaft wird in der Regel vom Hostanbieter bereitgestellt.

Ereignisse von Anbietern

Benutzeroberflächenautomatisierungs-Anbieter sollten Ereignisse auslösen, um Clientanwendungen über Zustandsänderungen der Benutzeroberfläche zu benachrichtigen. Die folgenden Funktionen werden verwendet, um Ereignisse auszulösen.

Funktion BESCHREIBUNG
UiaRaiseAutomationEvent Löst verschiedene Ereignisse aus, einschließlich Ereignissen, die von Steuerelementmustern ausgelöst werden.
UiaRaiseAutomationPropertyChangedEvent Löst ein Ereignis aus, wenn eine Benutzeroberflächenautomatisierungs-Eigenschaft geändert wurde.
UiaRaiseStructureChangedEvent Löst ein Ereignis aus, wenn sich die Struktur der Benutzeroberflächenautomatisierung-Struktur geändert hat, z. B. durch Entfernen oder Hinzufügen eines Elements.

 

Der Zweck eines Ereignisses besteht darin, den Client über etwas zu benachrichtigen, das auf der Benutzeroberfläche stattfindet. Anbieter sollten ein Ereignis auslösen, unabhängig davon, ob die Änderung durch Benutzereingaben oder durch eine Clientanwendung mit Benutzeroberflächenautomatisierung ausgelöst wurde. Beispielsweise sollte das durch UIA_Invoke_InvokedEventId identifizierte Ereignis ausgelöst werden, wenn das Steuerelement aufgerufen wird, entweder durch direkte Benutzereingabe oder durch die Clientanwendung, die IUIAutomationInvokePattern::Invoke aufruft.

Zum Optimieren der Leistung kann ein Anbieter Ereignisse selektiv auslösen oder keine Ereignisse auslösen, wenn für deren Empfang keine Clientanwendung registriert ist. Die folgenden API-Elemente werden zur Optimierung verwendet.

API-Element BESCHREIBUNG
UiaClientsAreListening Diese Funktion ermittelt, ob Clientanwendungen Benutzeroberflächenautomatisierung Ereignisse abonniert haben.
IRawElementProviderAdviseEvents Durch die Implementierung dieser Schnittstelle in einem Fragmentstamm kann der Anbieter informiert werden, wenn Clients Ereignishandler für Ereignisse im Fragment registrieren und die Registrierung aufheben.

 

Hinweis

Ähnlich wie bei der Implementierung der Referenzzählung in der COM-Programmierung ist es für Benutzeroberflächenautomatisierung Anbieter wichtig, die Methoden IRawElementProviderAdviseEvents::AdviseEventAdded und AdviseEventRemoved wie die IUnknown::AddRef- und Release-Methoden der IUnknown-Schnittstelle zu behandeln. Solange AdviseEventAdded für ein bestimmtes Ereignis oder eine bestimmte Eigenschaft häufiger aufgerufen wurde als AdviseEventRemoved , sollte der Anbieter weiterhin entsprechende Ereignisse auslösen, da einige Clients weiterhin lauschen. Alternativ können Benutzeroberflächenautomatisierung Anbieter die UiaClientsAreListening-Funktion verwenden, um zu bestimmen, ob mindestens ein Client lauscht, und wenn ja, alle entsprechenden Ereignisse auslösen.

 

Anbieternavigation

Anbieter für einfache Steuerelemente, z. B. eine benutzerdefinierte Schaltfläche, die in einem Fenster gehostet wird, müssen die Navigation in der Benutzeroberflächenautomatisierung-Struktur nicht unterstützen. Die Navigation zum und vom Element wird vom Standardanbieter für das Hostfenster verarbeitet, das in der Implementierung von IRawElementProviderSimple::HostRawElementProvider angegeben ist. Wenn Sie jedoch einen Anbieter für ein komplexes benutzerdefiniertes Steuerelement implementieren, müssen Sie die Navigation zwischen dem Stammknoten des Fragments und seinen Nachfolgern sowie zwischen nebengeordneten Knoten unterstützen.

Hinweis

Elemente eines anderen Fragments als dem Stamm müssen NULL von HostRawElementProvider zurückgeben, da sie nicht direkt in einem Fenster gehostet werden und kein Standardanbieter die Navigation zu und von ihnen unterstützen kann.

 

Die Struktur des Fragments wird durch Ihre Implementierung von IRawElementProviderFragment::Navigate bestimmt. Diese Methode gibt für jedes Fragment und jede mögliche Richtung das Anbieterobjekt für das in dieser Richtung liegende Element zurück. Wenn kein Element in dieser Richtung vorhanden ist, gibt die Methode NULL zurück.

Der Fragmentstamm unterstützt nur die Navigation zu untergeordneten Elementen. Beispielsweise gibt ein Listenfeld das erste Element in der Liste zurück, wenn die Richtung NavigateDirection_FirstChild ist, und das letzte Element zurück, wenn die Richtung NavigateDirection_LastChild ist. Der Fragmentstamm unterstützt keine Navigation zu einem übergeordneten Element oder zu gleichgeordneten Elementen. dies wird vom Hostfensteranbieter verarbeitet.

Die Nicht-Stammelemente eines Fragments müssen die Navigation zum übergeordneten Element sowie zu allen vorhandenen nebengeordneten und untergeordneten Elementen unterstützen.

Zuweisen eines neuen übergeordneten Elements

Popupfenster sind eigentlich Fenster der obersten Ebene und werden standardmäßig in der Benutzeroberflächenautomatisierung-Struktur als untergeordnete Elemente des Desktops angezeigt. Eigentlich sind Popupfenster in vielen Fällen jedoch untergeordnete Elemente anderer Steuerelemente. Beispielsweise ist die Dropdownliste eines Kombinationsfelds logischerweise ein untergeordnetes Element des Kombinationsfelds. Dementsprechend ist ein Menüpopupfenster logischerweise ein untergeordnetes Element des Menüs. Benutzeroberflächenautomatisierung unterstützt das Zuweisen eines neuen übergeordneten Elements zu einem Popupfenster, sodass es als untergeordnetes Element des zugeordneten Steuerelements erscheint.

So weisen Sie einem Popupfenster ein neues übergeordnetes Element zu:

  1. Erstellen Sie einen Anbieter für das Popupfenster. Dies erfordert, dass die Klasse des Popupfensters im Voraus bekannt ist.
  2. Implementieren Sie alle Eigenschaften und Steuerelementmuster wie gewohnt für dieses Popupfenster, als wäre es ein eigenes Steuerelement.
  3. Implementieren Sie die IRawElementProviderSimple::HostRawElementProvider-Eigenschaft , sodass sie den von UiaHostProviderFromHwnd abgerufenen Wert zurückgibt, wobei der Parameter das Fensterhandle des Popupfensters ist.
  4. Implementieren Sie IRawElementProviderFragment::Navigate für das Popupfenster und dessen übergeordnetes Fenster, damit die Navigation ordnungsgemäß vom logischen übergeordneten Element zu den logischen untergeordneten Elementen und zwischen untergeordneten Untergeordneten behandelt wird.

Wenn die Benutzeroberflächenautomatisierung auf das Popupfenster als untergeordnetes Element des Desktops stößt, wird erkannt, dass die Standardnavigation überschrieben wurde, und das Popupfenster wird übersprungen. Stattdessen ist der Knoten nur über das Fragment erreichbar.

Das Zuweisen eines neuen übergeordneten Elements eignet sich nicht für Fälle, in denen ein Steuerelement ein Fenster einer beliebigen Klasse hosten kann. Beispielsweise kann ein Beleistensteuerelement jede Art von Fenster in seinen Bändern hosten. Um diese Fälle zu behandeln, unterstützt Benutzeroberflächenautomatisierung eine alternative Form der Fensterverschiebung, wie im nächsten Abschnitt beschrieben.

Neupositionierung des Anbieters

Benutzeroberflächenautomatisierung Fragmente können zwei oder mehr Elemente enthalten, die jeweils in einem Fenster enthalten sind. Da jedes Fenster über einen eigenen Standardanbieter verfügt, der das Fenster als untergeordnetes Element eines enthaltenden Fensters betrachtet, zeigt die Benutzeroberflächenautomatisierung-Struktur standardmäßig die Fenster im Fragment als untergeordnete Elemente des übergeordneten Fensters an. Dies ist in den meisten Fällen erwünscht. Manchmal kann es jedoch zu Verwirrung führen, da es nicht der logischen Struktur der Benutzeroberfläche entspricht.

Ein gutes Beispiel hierfür ist ein Grundleistensteuerelement. Ein Balkensteuerelement enthält Bänder, die wiederum jeweils ein fensterbasiertes Steuerelement enthalten können, z. B. eine Symbolleiste, ein Bearbeitungsfeld oder ein Kombinationsfeld. Der Standardfensteranbieter für das Beleistenfenster sieht die Bandsteuerungsfenster als untergeordnete Elemente, und der Beleistenanbieter sieht die Bänder als untergeordnete Elemente. Da der Fensteranbieter und der Beleistenanbieter zusammen arbeiten und ihre untergeordneten Elemente kombinieren, werden sowohl die Bänder als auch die fensterbasierten Steuerelemente als untergeordnete Elemente des Beleistensteuerelements angezeigt. Logischerweise sollten jedoch nur die Bänder als untergeordnete Elemente des Rebar-Steuerelements angezeigt werden, und jeder Bandanbieter sollte mit dem Standardfensteranbieter für das darin enthaltene Steuerelement gekoppelt werden.

Um dies zu erreichen, macht der Fragmentstammanbieter für das Rebar-Steuerelement eine Reihe von untergeordneten Elementen verfügbar, die die Bänder darstellen. Jedes Band verfügt über einen einzelnen Anbieter, der Eigenschaften und Steuerelementmuster verfügbar macht. In seiner Implementierung von IRawElementProviderSimple::HostRawElementProvider gibt der Bandanbieter den Standardfensteranbieter für das Steuerelementfenster zurück, den er durch Aufrufen von UiaHostProviderFromHwnd erhält und dabei das Fensterhandle (HWND) des Steuerelements übergibt. Schließlich implementiert der Fragmentstammanbieter für die Rebar die IRawElementProviderHwndOverride-Schnittstelle und gibt in seiner Implementierung von IRawElementProviderHwndOverride::GetOverrideProviderForHwnd den entsprechenden Bandanbieter für das im angegebenen Fenster enthaltene Steuerelement zurück.

Trennen von Anbietern

Anwendungen erstellen in der Regel Steuerelemente, wenn sie benötigt werden, und zerstören sie anschließend. Nach dem Zerstören eines Steuerelements sollten die dem Steuerelement zugeordneten Benutzeroberflächenautomatisierung Anbieterressourcen durch Aufrufen von UiaDisconnectProvider freigegeben werden.

Ebenso sollte eine Anwendung die UiaDisconnectAllProviders-Funktion verwenden, um alle Benutzeroberflächenautomatisierung Ressourcen freizugeben, die von allen Anbietern in der Anwendung vor dem Herunterfahren gehalten werden.

Benutzeroberflächenautomatisierung Anbieterprogrammiererhandbuch