Implementierung eines serverseitigen Benutzeroberflächenautomatisierungs-Anbieters

Hinweis

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

In diesem Abschnitt wird beschrieben, wie ein serverseitiger Benutzeroberflächenautomatisierungs-Anbieter für ein benutzerdefiniertes Steuerelement implementiert wird.

Die Implementierung für Windows Presentation Foundation -Elemente (WPF) und Nicht-WPF-Elemente (z. B. für Windows Forms) unterscheidet sich grundlegend. WPF-Elemente bieten Unterstützung für Benutzeroberflächenautomatisierung über eine von abgeleitete AutomationPeer Klasse. Nicht-WPF-Elemente bieten Unterstützung durch Implementierungen von Anbieterschnittstellen.

Sicherheitsüberlegungen

Anbieter sollten so erstellt werden, dass sie in einer teilweise vertrauenswürdigen Umgebung funktionieren können. Da UIAutomationClient.dll nicht für die Ausführung mit teilweiser Vertrauenswürdigkeit konfiguriert ist, sollte der Anbietercode nicht auf diese Assembly verweisen. Wenn dies der Fall ist, kann der Code in einer voll vertrauenswürdigen Umgebung ausgeführt werden, während in einer teilweise vertrauenswürdigen Umgebung Fehler auftreten.

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

Anbieterimplementierung durch Windows Presentation Foundation-Elemente

Weitere Informationen zu diesem Thema finden Sie unter 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 (meistens sind dies Windows Forms-Steuerelemente), bieten Unterstützung für Benutzeroberflächenautomatisierung durch implementierung von Schnittstellen. Jedes Element muss mindestens eine der in der ersten Tabelle des nächsten Abschnitts aufgeführten Schnittstellen implementieren. Außerdem muss ein Element, das ein oder mehrere Steuerelementmuster unterstützt, für jedes Steuerelementmuster die entsprechende Schnittstelle implementieren.

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

  • UIAutomationProviders.dll

  • UIAutomationTypes.dll

  • WindowsBase.dll

Anbieterschnittstellen

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

Schnittstelle BESCHREIBUNG
IRawElementProviderSimple Stellt Funktionen für ein einfaches in einem Fenster gehostetes Steuerelement bereit, einschließlich der 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 im Fragment, Festlegen des Fokus und Zurückgeben des umschließenden Rechtecks des Elements.
IRawElementProviderFragmentRoot Erbt von IRawElementProviderFragment. 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.

Die folgenden Schnittstellen stellen weitere Funktionen bereit, müssen jedoch nicht implementiert werden.

Schnittstelle BESCHREIBUNG
IRawElementProviderAdviseEvents Ermöglicht dem Anbieter, Anforderungen für Ereignisse zu verfolgen.
IRawElementProviderHwndOverride Ermöglicht die Neupositionierung fensterbasierter Elemente innerhalb der Benutzeroberflächenautomatisierung Struktur eines Fragments.

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

Anforderungen für Nicht-WPF-Anbieter

Um mit Benutzeroberflächenautomatisierung kommunizieren zu können, muss Ihr Steuerelement die folgenden Hauptfunktionen implementieren:

Funktionalität Implementierung
Verfügbar machen des Anbieters für Benutzeroberflächenautomatisierung Antworten Sie auf eine an das Steuerelementfenster gesendete WM_GETOBJECT-Nachricht, indem Sie das Objekt zurückgeben, das IRawElementProviderSimple (oder eine abgeleitete Schnittstelle) implementiert. Für Fragmente muss dies der Anbieter für den Fragmentstamm sein.
Bereitstellen von Eigenschaftswerten Implementieren Sie GetPropertyValue , um Werte bereitzustellen oder zu überschreiben.
Ermöglichen der Interaktion des Clients mit dem Steuerelement Implementieren Sie Schnittstellen, die Steuerelementmuster unterstützen, z. B. IInvokeProvider. Geben Sie diese Musteranbieter in der Implementierung von GetPatternProviderzurück.
Auslösen von Ereignissen Rufen Sie eine der statischen Methoden von AutomationInteropProvider auf, um ein Ereignis auszulösen, das ein Client überwachen kann.
Ermöglichen der Navigation und Fokussierung in einem Fragment Implementieren Sie IRawElementProviderFragment für jedes Element innerhalb des Fragments. (Nicht für Elemente erforderlich, die kein Teil eines Fragments sind.)
Ermöglichen der Fokussierung und Positionierung eines untergeordneten Elements in einem Fragment Implementieren Sie IRawElementProviderFragmentRoot. (Nicht für Elemente erforderlich, die keine Fragmentstämme sind.)

Eigenschaftswerte in Nicht-WPF-Anbietern

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

Anbieter für HWND-basierte Steuerelemente müssen die folgenden Eigenschaften (identifiziert nach Feldwerten) normalerweise nicht bereitstellen:

Hinweis

Die RuntimeIdProperty eines in einem Fenster gehosteten einfachen Elements oder Fragmentstamms wird vom Fenster bezogen. Fragmentelemente unterhalb des Stamms (wie Listeneinträge in einem Listenfeld) müssen jedoch eigene Bezeichner bereitstellen. Weitere Informationen finden Sie unter GetRuntimeId.

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

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

Beispielcode finden Sie unter Return Properties from a UI Automation Provider.

Ereignisse in Nicht-WPF-Anbietern

Benutzeroberflächenautomatisierung Anbieter sollten Ereignisse auslösen, um Clientanwendungen über Änderungen im Zustand der Benutzeroberfläche zu benachrichtigen. Ereignisse werden mit den folgenden Methoden ausgelöst.

Methode BESCHREIBUNG
RaiseAutomationEvent Löst verschiedene Ereignisse aus, einschließlich Ereignissen, die von Steuerelementmustern ausgelöst werden.
RaiseAutomationPropertyChangedEvent Löst ein Ereignis aus, wenn sich eine Benutzeroberflächenautomatisierung-Eigenschaft geändert hat.
RaiseStructureChangedEvent Löst ein Ereignis aus, wenn sich die Struktur der Benutzeroberflächenautomatisierung Struktur geändert hat. z. B. durch das Entfernen oder Hinzufügen eines Elements.

Der Zweck eines Ereignisses besteht darin, den Client über etwas auf der Benutzeroberfläche (UI) zu benachrichtigen, unabhängig davon, ob die Aktivität vom Benutzeroberflächenautomatisierung System selbst ausgelöst wird oder nicht. Beispielsweise sollte das von InvokedEvent identifizierte Ereignis immer ausgelöst werden, wenn das Steuerelement aufgerufen wird, unabhängig davon, ob durch eine direkte Benutzereingabe oder durch die Invokeaufrufende Clientanwendung.

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 Methoden werden zur Optimierung verwendet.

Methode BESCHREIBUNG
ClientsAreListening Diese statische Eigenschaft gibt an, ob Clientanwendungen Benutzeroberflächenautomatisierung Ereignisse abonniert haben.
IRawElementProviderAdviseEvents Durch die Implementierung dieser Schnittstelle durch den Anbieter auf einem Fragmentstamm kann kommuniziert werden, wenn Clients Registrierungen von Ereignishandlern für Ereignisse im Fragment vornehmen bzw. aufheben.

Navigation für Nicht-WPF-Anbieter

Anbieter für einfache Steuerelemente, z. B. eine benutzerdefinierte Schaltfläche, die in einem Fenster gehostet wird (HWND), müssen die Navigation innerhalb der Benutzeroberflächenautomatisierung Struktur nicht unterstützen. Die Navigation zum und vom Element wird vom Standardanbieter für das Hostfenster verarbeitet, der in der Implementierung von HostRawElementProviderangegeben 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

Die Nicht-Stammelemente eines Fragments müssen einen null -Verweis von HostRawElementProviderzurückgeben, da sie nicht direkt in einem Fenster gehostet werden und die Navigation zu und von ihnen von keinem Standardanbieter unterstützt werden kann.

Die Struktur des Fragments wird durch Ihre Implementierung von Navigatefestgelegt. 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 in einer Richtung kein Element vorhanden ist, gibt die Methode einen null -Verweis zurück.

Der Fragmentstamm unterstützt nur die Navigation zu untergeordneten Elementen. Beispielsweise gibt ein Listenfeld für die Richtung FirstChildden ersten Eintrag und für die Richtung LastChildden letzten Eintrag in der Liste zurück. Der Fragmentstamm unterstützt keine Navigation zu einem übergeordneten oder nebengeordneten Element; diese 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.

Neuzuordnung des übergeordneten Elements für Nicht-WPF-Anbieter

Popupfenster sind eigentlich Fenster der obersten Ebene und werden daher 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 bietet Unterstützung für das erneute Auffüllen von Popupfenstern, sodass sie untergeordnete Elemente des zugeordneten Steuerelements zu sein scheinen.

So ordnen Sie ein Popupfenster einem neuen übergeordneten Element zu

  1. Erstellen Sie einen Anbieter für das Popupfenster. Hierfür muss die Klasse des Popupfensters im Voraus bekannt sein.

  2. Implementieren Sie für das Popupfenster alle Eigenschaften und Muster, als ob es ein vollkommen eigenständiges Steuerelement ist.

  3. Implementieren Sie die HostRawElementProvider -Eigenschaft, sodass sie den mit HostProviderFromHandleabgerufenen Wert zurückgibt. Der Parameter ist hierbei der Fensterhandle des Popupfensters.

  4. Implementieren Sie für das Popupfenster und das übergeordnete Element Navigate , sodass die Navigation vom logischen übergeordneten Element zum logischen untergeordneten Element sowie zwischen den nebengeordneten Elementen ordnungsgemäß verarbeitet wird.

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

Das Neuzuordnen des übergeordneten Elements ist nicht geeignet, wenn ein Steuerelement ein Fenster einer beliebigen Klasse hosten kann. Beispielsweise kann in den Bändern einer Grundleiste jeder HWND-Typ gehostet werden. Um diese Fälle zu behandeln, unterstützt Benutzeroberflächenautomatisierung eine alternative Form der HWND-Verschiebung, wie im nächsten Abschnitt beschrieben.

Neupositionieren für Nicht-WPF-Anbieter

Benutzeroberflächenautomatisierung Fragmente 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 die Benutzeroberflächenautomatisierung Struktur standardmäßig die HWNDs im Fragment als untergeordnete Elemente des übergeordneten Fensters an. In den meisten Fällen ist dies wünschenswert, kann aber manchmal zu Verwirrung führen, da es nicht mit der logischen Struktur der Benutzeroberfläche übereinstimmt.

Ein gutes Beispiel hierfür ist ein Grundleistensteuerelement. Eine Grundleiste enthält Bänder, die jeweils ein HWND-basiertes Steuerelement wie eine Symbolleiste, ein Eingabefeld oder ein Kombinationsfeld enthalten können. Für den Standardfensteranbieter für das Grundleisten-HWND sind die Bandsteuerelement-HWNDs untergeordnete Elemente, und für den Grundleistenanbieter sind die Bänder untergeordnete Elemente. Da der HWND-Anbieter und der Grundleistenanbieter zusammenarbeiten und ihre untergeordneten Elemente kombinieren, werden sowohl die Bänder als auch die HWND-basierten Steuerelemente als untergeordnete Elemente der Grundleiste angezeigt. Es sollten jedoch logischerweise nur die Bänder als untergeordnete Elemente der Grundleiste angezeigt werden, und jeder Bandanbieter sollte mit dem Standard-HWND-Anbieter für das enthaltene Steuerelement verbunden werden.

Hierfür stellt der Fragmentstammanbieter für die Grundleiste einen Satz an untergeordneten Elementen zur Verfügung, die die Bänder repräsentieren. Jedes Band verfügt über einen einzelnen Anbieter, der Eigenschaften und Muster zur Verfügung stellen kann. In dessen Implementierung von HostRawElementProvidergibt der Bandanbieter den Standardfensteranbieter für das Steuerelement-HWND zurück, den er unter Übergabe des Fensterhandles des Steuerelements mithilfe von HostProviderFromHandleabruft. Abschließend implementiert der Fragmentstammanbieter für die Infoleiste die IRawElementProviderHwndOverride -Schnittstelle, und gibt in seiner Implementierung von GetOverrideProviderForHwnd den geeigneten Bandanbieter für das im angegebenen HWND enthaltene Steuerelement zurück.

Siehe auch