Freigeben über


Die Implementierung des serverseitigen Anbieters für Benutzeroberflächenautomatisierung

Hinweis

Diese Dokumentation richtet sich an .NET Framework-Entwickler, die die verwalteten Benutzeroberflächenautomatisierungs-Klassen verwenden möchten, die im System.Windows.Automation-Namespace definiert sind. Die neuesten Informationen zur Benutzeroberflächenautomatisierung finden Sie unter Der Windows-Automatisierungs-API: Benutzeroberflächenautomatisierung.

In diesem Abschnitt wird beschrieben, wie Sie einen serverseitigen Benutzeroberflächenautomatisierungs-Anbieter für ein benutzerdefiniertes Steuerelement implementieren.

Die Implementierung für Windows Presentation Foundation (WPF)-Elemente und Nicht-WPF-Elemente (z. B. für Windows Forms entworfene Elemente) unterscheidet sich grundlegend. WPF-Elemente bieten Unterstützung für die UI-Automatisierung über eine Klasse, die von AutomationPeer abgeleitet ist. Nicht-WPF-Elemente bieten Unterstützung durch die Implementierung von Anbieterschnittstellen.

Sicherheitsüberlegungen

Anbieter sollten so geschrieben werden, dass sie in einer teilweise vertrauenswürdigen Umgebung arbeiten können. Da UIAutomationClient.dll nicht für die Ausführung unter teilweiser Vertrauensstellung konfiguriert ist, sollte ihr Anbietercode nicht auf diese Assembly verweisen. Wenn dies der Fall ist, kann der Code in einer voll vertrauenswürdigen Umgebung ausgeführt werden, aber in einer teilweise vertrauenswürdigen Umgebung fehlschlagen.

Verwenden Sie insbesondere keine Felder aus Klassen in UIAutomationClient.dll, z. B. in AutomationElement. Verwenden Sie stattdessen die entsprechenden Felder aus Klassen in UIAutomationTypes.dll, wie AutomationElementIdentifiers.

Anbieterimplementierung durch Windows Presentation Foundation-Elemente

Weitere Informationen zu diesem Thema finden Sie in der Benutzeroberflächenautomatisierung eines benutzerdefinierten WPF-Steuerelements.

Anbieterimplementierung durch Nicht-WPF-Elemente

Benutzerdefinierte Steuerelemente, die nicht Teil des WPF-Frameworks sind, aber in verwaltetem Code geschrieben sind (dies sind meist Windows Forms-Steuerelemente), bieten Unterstützung für die Benutzeroberflächenautomatisierung durch Implementieren von Schnittstellen. Jedes Element muss mindestens eine der Schnittstellen implementieren, die in der ersten Tabelle im nächsten Abschnitt aufgeführt sind. Wenn das Element ein oder mehrere Steuerelementmuster unterstützt, muss es außerdem die entsprechende Schnittstelle für jedes Steuerelementmuster implementieren.

Ihr Benutzeroberflächenautomatisierungs-Anbieterprojekt muss auf die folgenden Assemblys verweisen:

  • UIAutomationProviders.dll

  • UIAutomationTypes.dll

  • WindowsBase.dll

Anbieterschnittstellen

Jeder Benutzeroberflächenautomatisierungs-Anbieter muss eine der folgenden Schnittstellen implementieren.

Schnittstelle Beschreibung
IRawElementProviderSimple Stellt Funktionen für ein einfaches Steuerelement bereit, das in einem Fenster gehostet wird, einschließlich Unterstützung für Steuerelementmuster und -eigenschaften.
IRawElementProviderFragment Erbt von IRawElementProviderSimple. Fügt Funktionen für ein Element in einem komplexen Steuerelement hinzu, einschließlich Navigation innerhalb des Fragments, Festlegen des Fokus und Zurückgeben des Begrenzungsrechtecks des Elements.
IRawElementProviderFragmentRoot Erbt von IRawElementProviderFragment. Fügt Funktionen für das Stammelement in einem komplexen Steuerelement hinzu, einschließlich der Suche nach einem untergeordneten Element an angegebenen Koordinaten und Festlegen des Fokuszustands für das gesamte Steuerelement.

Die folgenden Schnittstellen stellen zusätzliche Funktionen bereit, müssen jedoch nicht implementiert werden.

Schnittstelle Beschreibung
IRawElementProviderAdviseEvents Ermöglicht es dem Anbieter, Anforderungen für Ereignisse nachzuverfolgen.
IRawElementProviderHwndOverride Ermöglicht die Neupositionierung von fensterbasierten Elementen innerhalb der Benutzeroberflächenautomatisierungs-Struktur eines Fragments.

Alle anderen Schnittstellen im System.Windows.Automation.Provider Namespace dienen zur Unterstützung von Steuerelementmustern.

Anforderungen für Nicht-WPF-Anbieter

Um mit der Benutzeroberflächenautomatisierung zu kommunizieren, muss Ihr Steuerelement die folgenden Hauptbereiche der Funktionalität implementieren:

Funktionalität Implementation
Den Anbieter der Benutzeroberflächenautomatisierung aussetzen Geben Sie als Reaktion auf eine an das Steuerelementfenster gesendete WM_GETOBJECT-Nachricht das Objekt zurück, das IRawElementProviderSimple implementiert (oder eine abgeleitete Schnittstelle). Bei Fragmenten muss dies der Anbieter für den Fragmentstamm sein.
Bereitstellen von Eigenschaftswerten Implementieren Sie GetPropertyValue, um Werte bereitzustellen oder außer Kraft zu setzen.
Ermöglichen der Interaktion mit dem Steuerelement durch den Client Implementieren Sie Schnittstellen, die Steuerelementmuster unterstützen, wie z. B. IInvokeProvider. Geben Sie diese Musteranbieter in Ihrer Implementierung von GetPatternProvider.
Auslösen von Ereignissen Rufen Sie eine der statischen Methoden AutomationInteropProvider zum Auslösen eines Ereignisses auf, auf das ein Client lauschen kann.
Aktivieren der Navigation und Fokussierung innerhalb eines Fragments Implementieren Sie IRawElementProviderFragment für jedes Element innerhalb des Fragments. (Nicht erforderlich für Elemente, die nicht Teil eines Fragments sind.)
Aktivieren des Fokus und der Position des untergeordneten Elements in einem Fragment Implementieren Sie IRawElementProviderFragmentRoot. (Nicht erforderlich für Elemente, die keine Fragmentwurzeln sind.)

Eigenschaftswerte in Nicht-WPF-Anbietern

Benutzeroberflächenautomatisierungs-Anbieter für benutzerdefinierte Steuerelemente müssen bestimmte Eigenschaften unterstützen, die vom Automatisierungssystem sowie von Clientanwendungen verwendet werden können. Bei Elementen, die in Windows (HWNDs) gehostet werden, kann die Benutzeroberflächenautomatisierung einige Eigenschaften vom Standardfensteranbieter abrufen, muss jedoch andere vom benutzerdefinierten Anbieter abrufen.

Anbieter für HWND-basierte Steuerelemente müssen in der Regel nicht die folgenden Eigenschaften (durch Feldwerte identifiziert) bereitstellen:

Hinweis

Das in einem Fenster gehostete einfache Element oder der Stamm eines Fragments wird von dem Fenster abgerufen; jedoch müssen Elemente unterhalb des Stammfragments (wie etwa Listenelemente in einem Listenfeld) ihre eigenen Bezeichner bereitstellen. Weitere Informationen finden Sie unter GetRuntimeId.

Das IsKeyboardFocusableProperty sollte für Dienstanbieter zurückgegeben werden, die in einem Windows Forms-Steuerelement gehostet werden. In diesem Fall kann der Standardfensteranbieter den richtigen Wert möglicherweise nicht abrufen.

Dies NameProperty wird in der Regel vom Hostanbieter bereitgestellt. Wenn beispielsweise ein benutzerdefiniertes Steuerelement von Control abgeleitet wird, wird der Name von der Text-Eigenschaft des Steuerelements abgeleitet.

Beispielcode finden Sie unter "Rückgabeeigenschaften von einem Benutzeroberflächenautomatisierungsanbieter".

Ereignisse in Nicht-WPF-Anbietern

Benutzeroberflächenautomatisierungs-Anbieter sollten Ereignisse auslösen, um Clientanwendungen über Änderungen im Zustand der Benutzeroberfläche zu benachrichtigen. Die folgenden Methoden werden zum Auslösen von Ereignissen verwendet.

Methode Beschreibung
RaiseAutomationEvent Löst verschiedene Ereignisse aus, einschließlich von Steuerelementmustern ausgelöste Ereignisse.
RaiseAutomationPropertyChangedEvent Löst ein Ereignis aus, wenn sich eine UI-Automatisierungs-Eigenschaft geändert hat.
RaiseStructureChangedEvent Löst ein Ereignis aus, wenn sich die Struktur des Benutzeroberflächenautomatisierungsbaums geändert hat; beispielsweise durch das Entfernen oder Hinzufügen eines Elements.

Der Zweck eines Ereignisses besteht darin, den Client darüber zu informieren, dass etwas in der Benutzeroberfläche stattfindet, unabhängig davon, ob die Aktivität vom Benutzeroberflächenautomatisierungssystem selbst ausgelöst wird. Beispielsweise sollte das Ereignis, das von InvokedEvent identifiziert wird, ausgelöst werden, wenn das Steuerelement aufgerufen wird, entweder durch direkte Benutzereingabe oder durch den Aufruf von Invoke durch die Clientanwendung.

Um die Leistung zu optimieren, kann ein Anbieter selektiv Ereignisse auslösen oder gar keine Ereignisse auslösen, wenn keine Clientanwendung registriert ist, um sie zu empfangen. Die folgenden Methoden werden zur Optimierung verwendet.

Methode Beschreibung
ClientsAreListening Diese statische Eigenschaft gibt an, ob Clientanwendungen Benutzeroberflächenautomatisierungs-Ereignisse abonniert haben.
IRawElementProviderAdviseEvents Die Implementierung dieser Schnittstelle auf einem Fragment-Stamm ermöglicht es dem Anbieter, benachrichtigt zu werden, wenn Clients Ereignishandler für Ereignisse im Fragment registrieren und abmelden.

Nicht-WPF-Anbieternavigation

Anbieter für einfache Steuerelemente wie eine benutzerdefinierte Schaltfläche, die in einem Fenster (HWND) gehostet wird, müssen die Navigation in der Benutzeroberflächenautomatisierungs-Struktur nicht unterstützen. Die Navigation zu und von dem Element wird vom Standardanbieter für das Hostfenster gehandhabt, wie in der Implementierung von HostRawElementProvider angegeben. Wenn Sie einen Anbieter für ein komplexes benutzerdefiniertes Steuerelement implementieren, müssen Sie jedoch die Navigation zwischen dem Stammknoten des Fragments und dessen Nachfolgern und zwischen gleichgeordneten Knoten unterstützen.

Hinweis

Elemente eines Fragmentelements, das nicht der Stamm ist, müssen einen null-Verweis von HostRawElementProvider zurückgeben, da sie nicht direkt in einem Fenster gehostet werden; kein Standardanbieter kann die Navigation zu und von ihnen unterstützen.

Die Struktur des Fragments wird durch Ihre Implementierung Navigate bestimmt. Für jede mögliche Richtung aus jedem Fragment gibt diese Methode das Anbieterobjekt für das Element in dieser Richtung zurück. Wenn in dieser Richtung kein Element vorhanden ist, gibt die Methode einen null Verweis zurück.

Der Fragmentstamm unterstützt die Navigation nur zu untergeordneten Elementen. Ein Listenfeld gibt z. B. das erste Element in der Liste zurück, wenn die Richtung lautet FirstChild, und das letzte Element, wenn die Richtung lautet LastChild. Der Fragmentstamm unterstützt keine Navigation zu einem übergeordneten oder gleichgeordneten Element; Dies wird vom Hostfenster-Provider behandelt.

Elemente eines Fragments, das nicht der Stamm ist, müssen die Navigation zu dem übergeordneten Element und allen gleichgeordneten Elementen und untergeordneten Elementen unterstützen, die sie haben.

Nicht-WPF-Anbieter-Analyse

Popupfenster sind eigentlich Fenster der obersten Ebene und werden daher standardmäßig in der Benutzeroberflächenautomatisierungs-Struktur als untergeordnete Elemente des Desktops angezeigt. In vielen Fällen sind Popupfenster jedoch logisch untergeordnete Elemente eines anderen Steuerelements. Die Dropdownliste eines Kombinationsfelds ist beispielsweise logisch ein Kind des Kombinationsfelds. Ebenso ist ein Popupfenster eines Menüs logisch ein untergeordnetes Element des Menüs. Die Benutzeroberflächenautomatisierung bietet Unterstützung für das Neuverknüpfen von Popupfenstern, sodass sie als Kinder des zugeordneten Steuerelements erscheinen.

So stellen Sie ein Popupfenster wieder bereit:

  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 Muster wie gewohnt für dieses Popup, als wäre es ein eigenständiges Steuerelement.

  3. Implementieren Sie die HostRawElementProvider-Eigenschaft so, dass sie den von ihr mithilfe von HostProviderFromHandle abgerufenen Wert zurückgibt, wobei der Parameter das Fenster-Handle des Popupfensters ist.

  4. Implementieren Sie Navigate für das Popupfenster und das übergeordnete Fenster, sodass die Navigation ordnungsgemäß vom logischen übergeordneten Element zu den logischen untergeordneten Elementen und zwischen gleichgeordneten untergeordneten Elementen behandelt wird.

Wenn die Benutzeroberflächenautomatisierung auf das Popupfenster trifft, erkennt sie, dass die Navigation vom Standard außer Kraft gesetzt wird, und überspringt das Popupfenster, wenn es als untergeordnetes Element des Desktops erkannt wird. Stattdessen ist der Knoten nur über das Fragment erreichbar.

Reparenting ist nicht geeignet für Fälle, in denen ein Steuerelement ein Fenster einer beliebigen Klasse hosten kann. Beispielsweise kann eine Rebar einen beliebigen HWND-Typ in seinen Bändern hosten. Zur Behandlung dieser Fälle unterstützt die Benutzeroberflächenautomatisierung eine alternative Form der HWND-Verlagerung, wie im nächsten Abschnitt beschrieben.

Neupositionierung von Nicht-WPF-Anbietern

Benutzeroberflächenautomatisierungsfragmente können zwei oder mehr Elemente enthalten, die jeweils in einem Fenster (HWND) enthalten sind. Da jeder HWND über einen eigenen Standardanbieter verfügt, der den HWND als untergeordnetes Element eines enthaltenden HWND betrachtet, zeigt der UI-Automationsbaum standardmäßig die HWNDs im Fragment als untergeordnete Elemente des übergeordneten Fensters an. In den meisten Fällen ist dies wünschenswertes Verhalten, kann aber manchmal zu Verwirrung führen, da sie nicht mit der logischen Struktur der Benutzeroberfläche übereinstimmt.

Ein gutes Beispiel hierfür ist ein Rebar-Steuerelement. Eine Rebar enthält Bänder, von denen jedes wiederum ein HWND-basiertes Steuerelement wie eine Symbolleiste, ein Bearbeitungsfeld oder ein Kombinationsfeld enthalten kann. Der Standardfensteranbieter für die Rebar-HWND sieht die HWNDs der Bandsteuerung als untergeordnete Elemente an, und der Rebar-Anbieter sieht die Bänder als untergeordnete Elemente. Da der HWND-Anbieter und der Rebar-Anbieter zusammen arbeiten und ihre untergeordneten Elemente kombinieren, werden sowohl die Bänder als auch die HWND-basierten Steuerelemente als untergeordnete Elemente der Rebar angezeigt. Logisch sollten jedoch nur die Bands als untergeordnete Elemente der Rebar erscheinen, und jeder Bandanbieter sollte mit dem standardmäßigen HWND-Anbieter für das enthaltene Steuerelement gekoppelt sein.

Dazu macht der Fragmentstammanbieter für die Rebar eine Gruppe untergeordneter Elemente verfügbar, die die Bänder darstellen. Jedes Band verfügt über einen einzelnen Anbieter, der Eigenschaften und Muster verfügbar macht. In seiner Implementierung gibt HostRawElementProvider der Bandanbieter den Standardfensteranbieter für das Steuerelement HWND zurück, den er durch Aufrufen von HostProviderFromHandle erhält, indem er das Fensterhandle des Steuerelements übergibt. Schließlich implementiert der Fragmentstammanbieter für die Rebar die IRawElementProviderHwndOverride-Schnittstelle und gibt in seiner Implementierung von GetOverrideProviderForHwnd den entsprechenden Bandanbieter für das Steuerelement zurück, das im angegebenen HWND enthalten ist.

Siehe auch