Implementierung eines serverseitigen Benutzeroberflächenautomatisierungs-Anbieters

Aktualisiert: November 2007

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

Die Implementierungen für Windows Presentation Foundation (WPF)-Elemente und Nicht-WPF-Elemente (z. B. mit Windows Forms entworfene Elemente) unterscheiden sind grundlegend. WPF-Elemente stellen die Unterstützung für UI-Automatisierung über eine Klasse bereit, die von AutomationPeer abgeleitet ist. Nicht-WPF-Elemente stellen die Unterstützung durch Implementierungen von Anbieterschnittstellen bereit.

Dieses Thema enthält folgende Abschnitte.

  • Sicherheitsüberlegungen
  • Anbieterimplementierung durch Windows Presentation Foundation-Elemente
  • Anbieterimplementierung durch Nicht-WPF-Elemente
  • Verwandte Abschnitte

Sicherheitsüberlegungen

Anbieter sollten so geschrieben 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. Andernfalls kann der Code in einer Umgebung mit voller Vertrauenswürdigkeit ausgeführt werden, in teilweise vertrauenswürdigen Umgebungen tritt jedoch ein Fehler auf.

Verwenden Sie insbesondere keine Felder der Klassen in UIAutomationClient.dll, z. B. aus 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 UI-Automatisierung 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 UI-Automatisierung-Anbieterprojekt muss auf die folgenden Assemblys verweisen:

  • UIAutomationProviders.dll

  • UIAutomationTypes.dll

  • WindowsBase.dll

Dieser Abschnitt enthält folgende Unterabschnitte.

  • Anbieterschnittstellen
  • Anforderungen für Nicht-WPF-Anbieter
  • Eigenschaftenwerte in Nicht-WPF-Anbietern
  • Ereignisse in Nicht-WPF-Anbietern
  • Navigation für Nicht-WPF-Anbieter
  • Neuzuordnung des übergeordneten Elements für Nicht-WPF-Anbieter
  • Neupositionieren für Nicht-WPF-Anbieter

Anbieterschnittstellen

Jeder UI-Automatisierung-Anbieter muss eine der folgenden Schnittstellen implementieren.

Schnittstelle

Beschreibung

IRawElementProviderSimple

Stellt Funktionalität 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 Funktionalität 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 Funktionalität 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 Neupositionieren von fensterbasierten Elementen innerhalb der UI-Automatisierung-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 UI-Automatisierung zu kommunizieren, muss ein Steuerelement die folgenden Hauptfunktionalitätsbereiche implementieren:

Funktionalität

Implementierung

Verfügbarmachen des Anbieters für UI-Automatisierung

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 Eigenschaftenwerten

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 GetPatternProvider zurü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

Sie können IRawElementProviderFragmentRoot implementieren. (Nicht für Elemente erforderlich, die keine Fragmentstämme sind.)

Eigenschaftenwerte in Nicht-WPF-Anbietern

UI-Automatisierung-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 UI-Automatisierung 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.

Die 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 Control abgeleitet ist, wird der Name von der Text-Eigenschaft des Steuerelements abgeleitet.

Beispielcode finden Sie unter Zurückgeben von Eigenschaften aus einem Benutzeroberflächenautomatisierungs-Anbieter.

Ereignisse in Nicht-WPF-Anbietern

UI-Automatisierung-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 sich eine UI-Automatisierung-Eigenschaft geändert hat.

RaiseStructureChangedEvent

Löst ein Ereignis aus, wenn sich der Aufbau der UI-Automatisierung-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 in der Benutzeroberfläche (user interface, UI), unabhängig davon, ob eine Aktion vom UI-Automatisierung-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 Invoke aufrufende 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 UI-Automatisierung-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.

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

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 Navigate festgelegt. 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 die Navigation nur zu untergeordneten Elementen. Beispielsweise gibt ein Listenfeld für die Richtung FirstChild den ersten Eintrag und für die Richtung LastChild den 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 UI-Automatisierung-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 UI-Automatisierung 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 HostProviderFromHandle abgerufenen 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 UI-Automatisierung 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 Infoleiste jeder HWND-Typ gehostet werden. Für solche Fälle unterstützt die UI-Automatisierung eine alternative Form der HWND-Umsetzung. Diese wird im nächsten Abschnitt beschrieben.

Neupositionieren für Nicht-WPF-Anbieter

UI-Automatisierung-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 UI-Automatisierung-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 Infoleistensteuerelement. Eine Infoleiste 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 Infoleisten-HWND sind die Bandsteuerelement-HWNDs untergeordnete Elemente, und für den Infoleistenanbieter sind die Bänder untergeordnete Elemente. Da der HWND-Anbieter und der Infoleistenanbieter zusammenarbeiten und ihre untergeordneten Elemente kombinieren, werden sowohl die Bänder als auch die HWND-basierten Steuerelemente als untergeordnete Elemente der Infoleiste angezeigt. Logisch sollten jedoch nur die Bänder als untergeordnete Elemente der Infoleiste 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 Infoleiste 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 HostRawElementProvider gibt der Bandanbieter den Standardfensteranbieter für das Steuerelement-HWND zurück, den er unter Übergabe des Fensterhandles des Steuerelements mithilfe von HostProviderFromHandle abruft. 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

Aufgaben

Verfügbarmachen eines serverseitigen Benutzeroberflächenautomatisierungs-Anbieters

Zurückgeben von Eigenschaften aus einem Benutzeroberflächenautomatisierungs-Anbieter

Auslösen von Ereignissen aus einem Benutzeroberflächenautomatisierungs-Anbieter

Aktivieren der Navigation in einem Benutzeroberflächenautomatisierungs-Fragmentanbieter

Unterstützung von Steuerelementmustern in einem Benutzeroberflächenautomatisierungs-Anbieter

Beispiel für einen einfachen Anbieter

Beispiel für einen Fragmentanbieter

Konzepte

Übersicht über die Benutzeroberflächenautomatisierungs-Anbieter