Implementierung eines serverseitigen Benutzeroberflächenautomatisierungs-Anbieters

Hinweis

Diese Dokumentation ist für .NET Framework-Entwickler konzipiert, die die verwalteten Klassen zur Automatisierung der Benutzeroberfläche verwenden möchten, die im Namespace System.Windows.Automation definiert sind. Aktuelle Informationen zur Automatisierung der Benutzeroberfläche finden Sie auf der Seite zur Windows-Automatisierungs-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 entworfene Elemente) unterscheidet sich grundlegend. WPF-Elemente bieten Unterstützung für die Benutzeroberflächenautomatisierung über eine von AutomationPeer abgeleitete Klasse. Nicht-WFP-Elemente stellen die Unterstützung durch Implementierungen von Anbieterschnittstellen bereit.

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, jedoch in verwaltetem Code geschrieben sind (hierbei handelt es sich meist um Windows Forms-Steuerelemente), unterstützen die Benutzeroberflächenautomatisierung durch das Implementieren 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.

Das Projekt für den Benutzeroberflächenautomatisierungs-Anbieter 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 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 das Ändern der Position von fensterbasierten Elementen innerhalb der Benutzeroberflächenautomatisierungs-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 der Benutzeroberflächenautomatisierung zu kommunizieren, muss ein Steuerelement die folgenden Hauptfunktionalitätsbereiche implementieren:

Funktionalität Implementierung
Verfügbarmachen des Anbieters für die 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ächenautomatisierungs-Anbieter für benutzerdefinierte Steuerelemente müssen bestimmte Eigenschaften unterstützen, die sowohl vom Automatisierungssystem als auch von Clientanwendungen verwendet werden können. Bei in Fenstern gehosteten Elementen (HWNDs) kann die Benutzeroberflächenautomatisierung einige Eigenschaften vom Standardfensteranbieter abrufen, andere müssen jedoch vom benutzerdefinierten Anbieter bezogen werden.

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.

IsKeyboardFocusableProperty 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 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ächenautomatisierungs-Anbieter sollten Ereignisse auslösen, um Clientanwendungen über Zustandsänderungen 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 eine Benutzeroberflächenautomatisierungs-Eigenschaft geändert wurde.
RaiseStructureChangedEvent Löst ein Ereignis aus, wenn sich der Aufbau der Benutzeroberflächenautomatisierungs-Struktur geändert hat, z. B. durch Entfernen oder Hinzufügen eines Elements.

Der Zweck eines Ereignisses liegt im Benachrichtigen des Clients über Vorgänge auf der Benutzeroberfläche, unabhängig davon, ob die Aktion vom Benutzeroberflächenautomatisierungs-System selbst ausgelöst wird. 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 es Clientanwendungen gibt, die Benutzeroberflächenautomatisierungs-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 (HWND) gehostet wird, müssen die Navigation innerhalb der Benutzeroberflächenautomatisierungs-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 HostRawElementProvider zurü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

Genau genommen sind Popupfenster Fenster oberster Ebene und werden in der Benutzeroberflächenautomatisierungs-Struktur standardmäßig 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. Die Benutzeroberflächenautomatisierung unterstützt für Popupfenster das Neuzuordnen des übergeordneten Elements, sodass sie als untergeordnete Elemente des zugehörigen Steuerelements angezeigt werden.

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 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 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. Für solche Fälle unterstützt die Benutzeroberflächenautomatisierung eine alternative Form der HWND-Verschiebung. Diese wird im nächsten Abschnitt beschrieben.

Neupositionieren für Nicht-WPF-Anbieter

Benutzeroberflächenautomatisierungs-Fragmente enthalten möglicherweise zwei oder mehr Elemente, die jeweils in einem Fenster (HWND) enthalten sind. Da jedes HWND über einen eigenen Standardanbieter verfügt, der das HWND als ein untergeordnetes Element eines enthaltenden HWND ansieht, werden in der Benutzeroberflächenautomatisierungs-Struktur die HWNDs im Fragment standardmäßig als untergeordnete Elemente des übergeordneten Fensters angezeigt. 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. 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