Implementazione del provider di automazione interfaccia utente lato server

Nota

Questa documentazione è destinata agli sviluppatori .NET Framework che desiderano utilizzare le classi di UI Automation gestite definite nello spazio dei nomi System.Windows.Automation. Per informazioni aggiornate su UI Automation, vedere API di automazione di Windows: UI Automation.

In questa sezione viene descritto come implementare un provider di automazione interfaccia utente sul lato server per un controllo personalizzato.

L'implementazione per gli elementi di Windows Presentation Foundation (WPF) e gli elementi non WPF (ad esempio quelli progettati per Windows Form) è fondamentalmente diversa. Gli elementi WPF forniscono il supporto per l'automazione interfaccia utente tramite una classe derivata da AutomationPeer. Gli elementi non WPF forniscono supporto tramite implementazioni di interfacce del provider.

Security Considerations

I provider devono essere scritti in modo che possano operare in un ambiente parzialmente attendibile. Dato che UIAutomationClient.dll non è configurato per l'esecuzione con attendibilità parziale, il codice del provider non dovrebbe fare riferimento a tale assembly. In caso contrario, il codice potrebbe essere eseguito in un ambiente con attendibilità completa, ma poi generare errori in un ambiente parzialmente attendibile.

In particolare, non usare campi delle classi in UIAutomationClient.dll come quelle in AutomationElement. Usare invece i campi equivalenti dalle classi in UIAutomationTypes.dll, come AutomationElementIdentifiers.

Implementazione di provider da elementi di Windows Presentation Foundation

Per altre informazioni su questo argomento, vedere Automazione interfaccia utente di un controllo personalizzato WPF.

Implementazione di provider da elementi non WPF

I controlli personalizzati che non fanno parte del framework WPF, ma scritti in codice gestito (in genere si tratta di controlli Windows Forms), offrono il supporto per l’automazione dell’interfaccia utente tramite l'implementazione di interfacce. Ogni elemento deve implementare almeno una delle interfacce elencate nella prima tabella nella sezione successiva. Inoltre, se l'elemento supporta uno o più pattern di controllo, deve implementare l'interfaccia appropriata per ognuno di essi.

Il progetto del provider di automazione dell’interfaccia utente deve fare riferimento agli assembly seguenti:

  • UIAutomationProviders.dll

  • UIAutomationTypes.dll

  • WindowsBase.dll

Interfacce del provider

Ogni provider di automazione dell’interfaccia utente deve implementare una delle interfacce seguenti.

Interfaccia Descrizione
IRawElementProviderSimple Fornisce funzionalità per un controllo semplice ospitato in una finestra, incluso il supporto per pattern di controllo e proprietà.
IRawElementProviderFragment Eredita dall'oggetto IRawElementProviderSimple. Aggiunge la funzionalità per un elemento in un controllo complesso, inclusi lo spostamento all'interno del frammento, l'impostazione dello stato attivo e la restituzione del rettangolo delimitatore dell'elemento.
IRawElementProviderFragmentRoot Eredita dall'oggetto IRawElementProviderFragment. Aggiunge la funzionalità per l'elemento radice in un controllo complesso, inclusi l'individuazione di un elemento figlio in corrispondenza delle coordinate specificate e l'impostazione dello stato attivo per l'intero controllo.

Le interfacce seguenti offrono ulteriori funzionalità, ma la loro implementazione non è richiesta.

Interfaccia Descrizione
IRawElementProviderAdviseEvents Consente al provider di tenere traccia delle richieste per eventi.
IRawElementProviderHwndOverride Abilita il riposizionamento degli elementi basati su finestra all'interno dell'albero di automazione dell’interfaccia utenet di un frammento.

Tutte le altre interfacce nello spazio dei nomi System.Windows.Automation.Provider sono destinate al supporto dei pattern di controllo.

Requisiti per i provider non WPF

Per comunicare con l’automazione dell’interfaccia utente, il tuo controllo deve implementare le aree di funzionalità principali seguenti:

Funzionalità Implementazione
Esporre il provider all'automazione interfaccia utente In risposta a un messaggio WM_GETOBJECT inviato alla finestra del controllo, restituire l'oggetto che implementa IRawElementProviderSimple (o un'interfaccia derivata). Per i frammenti, deve trattarsi del provider per la radice del frammento.
Fornire i valori delle proprietà Implementare GetPropertyValue per fornire i valori o eseguirne l'override.
Consentire al client di interagire con il controllo Implementare le interfacce che supportano pattern di controllo, ad esempio IInvokeProvider. Restituire questi provider di pattern nell'implementazione di GetPatternProvider.
Generare eventi Chiamare uno dei metodi statici di AutomationInteropProvider per generare un evento di cui un client può rimanere in ascolto.
Abilitare la navigazione e lo spostamento dello stato attivo all'interno di un frammento Implementare IRawElementProviderFragment per ogni elemento all'interno del frammento. (Non necessario per gli elementi che non fanno parte di un frammento).
Abilitare lo spostamento dello stato attivo e il posizionamento dell'elemento figlio in un frammento Implementare IRawElementProviderFragmentRoot. (Non necessario per gli elementi che non sono radici di frammenti).

Valori delle proprietà nei provider non WPF

I provider di automazione dell’interfaccia utente per i controlli personalizzati devono supportare determinate proprietà che possono essere usate dai sistemi di automazione ed anche dalle applicazioni client. Per gli elementi ospitati nelle finestre (HWND), l’automazione dell’interfaccia utente può recuperare alcune proprietà dal provider di finestra predefinito, ma deve ottenerne altre dal provider personalizzato.

I provider per i controlli basati su HWND in genere non richiedono di specificare le proprietà seguenti (identificate da valori di campo):

Nota

Il valore RuntimeIdProperty di un elemento semplice o di una radice di frammento ospitato in una finestra viene ottenuto dalla finestra. Tuttavia, gli elementi del frammento sotto la radice (ad esempio voci di elenco in una casella di riepilogo) devono fornire i propri identificatori. Per ulteriori informazioni, vedere GetRuntimeId.

IsKeyboardFocusableProperty deve essere restituito per i provider ospitati in un controllo Windows Form. In questo caso, il provider di finestra predefinito potrebbe non essere in grado di recuperare il valore corretto.

Il valore NameProperty viene in genere fornito dal provider host. Ad esempio, se un controllo personalizzato è derivato da Control, il nome è derivato dalla proprietà Text del controllo.

Per il codice di esempio, vedere Return Properties from a UI Automation Provider.

Eventi nei provider non WPF

I provider di automazione interfaccia utente devono generare eventi per notificare alle applicazioni client modifiche nello stato dell'interfaccia utente. Per generare gli eventi vengono usati i metodi seguenti.

metodo Descrizione
RaiseAutomationEvent Genera vari eventi, inclusi gli eventi attivati dai pattern di controllo.
RaiseAutomationPropertyChangedEvent Genera un evento quando viene modificata una proprietà di automazione interfaccia utente.
RaiseStructureChangedEvent Genera un evento quando la struttura dell'albero di automazione interfaccia utente è cambiata; ad esempio, mediante la rimozione o l'aggiunta di un elemento.

Lo scopo di un evento è notificare al client un evento che si verifica nell'interfaccia utente, indipendentemente dal fatto che l'attività venga attivata dal sistema di automazione interfaccia utente stesso. Ad esempio, l'evento identificato da InvokedEvent dovrebbe essere generato ogni volta che viene richiamato il controllo, sia tramite input diretto dell'utente o dall'applicazione client che chiama Invoke.

Per ottimizzare le prestazioni, un provider può generare eventi in modo selettivo o non generarne affatto se nessuna applicazione client è registrata per riceverli. Per l'ottimizzazione vengono usati i metodi seguenti.

metodo Descrizione
ClientsAreListening Questa proprietà statica specifica se le applicazioni client hanno sottoscritto eventi di automazione interfaccia utente.
IRawElementProviderAdviseEvents L'implementazione del provider di questa interfaccia in una radice di frammento consente di ricevere notifica quando i client registrano e annullano la registrazione di gestori eventi per gli eventi nel frammento.

Navigazione per i provider non WPF

I provider per controlli semplici, ad esempio un pulsante personalizzato ospitato in una finestra (HWND), non devono supportare lo spostamento all'interno dell'albero di automazione interfaccia utente. La navigazione verso e dall'elemento viene gestita dal provider predefinito per la finestra host specificato nell'implementazione di HostRawElementProvider. Quando si implementa un provider per un controllo personalizzato complesso, tuttavia, è necessario supportare la navigazione tra il nodo radice del frammento e i relativi discendenti, nonché tra nodi di pari livello.

Nota

Gli elementi di un frammento diversi dalla radice devono restituire un riferimento a null da HostRawElementProvider, perché non sono ospitati direttamente in una finestra e nessun provider predefinito può supportare lo spostamento verso e da tali elementi.

La struttura del frammento è determinata dall'implementazione di Navigate. Per ogni possibile direzione da ogni frammento, questo metodo restituisce l'oggetto provider per l'elemento in quella direzione. Se non è presente alcun elemento nella direzione specificata, il metodo restituisce un riferimento a null .

La radice del frammento supporta la navigazione solo verso gli elementi figlio. Ad esempio, una casella di riepilogo restituisce il primo elemento nell'elenco quando la direzione è FirstChilde l'ultimo elemento quando la direzione è LastChild. La radice del frammento non supporta la navigazione verso un elemento padre o elementi di pari livello. Questa operazione viene gestita dal provider della finestra host.

Gli elementi di un frammento non radice devono supportare la navigazione verso l'elemento padre e verso eventuali elementi di pari livello e figli.

Associazione con un nuovo elemento padre per i provider non WPF

Le finestre popup sono in realtà finestre di primo livello, quindi per impostazione predefinita vengono visualizzate nell'albero di automazione interfaccia utente come elementi figlio del desktop. In molti casi, tuttavia, le finestre popup sono logicamente elementi figlio di un altro controllo. Ad esempio, l'elenco a discesa di una casella combinata è logicamente un elemento figlio della casella combinata. Analogamente, una finestra popup di menu è logicamente un elemento figlio del menu. Automazione interfaccia utente fornisce supporto per le finestre popup simultanee in modo che sembrino elementi figlio del controllo associato.

Per associare una finestra popup con un nuovo elemento padre:

  1. Creare un provider per la finestra popup. È necessario che la classe della finestra popup sia nota in anticipo.

  2. Implementare tutte le proprietà e i pattern come di consueto per tale popup, come se fosse un controllo.

  3. Implementare la proprietà HostRawElementProvider in modo che restituisca il valore ottenuto da HostProviderFromHandle, dove il parametro è l'handle della finestra popup.

  4. Implementare Navigate per la finestra popup e il relativo elemento padre in modo che la navigazione venga gestita correttamente dall'elemento padre logico agli elementi figlio logici e tra gli elementi figlio di pari livello.

Quando Automazione interfaccia utente rileva la finestra popup, riconosce che lo spostamento viene sottoposto a override dal valore predefinito e ignora la finestra popup quando viene rilevato come figlio del desktop. Al contrario, il nodo sarà raggiungibile solo tramite il frammento.

L'associazione con un nuovo elemento padre non è appropriata nei casi in cui un controllo può ospitare una finestra di qualsiasi classe. Ad esempio, un controllo Rebar può contenere qualsiasi tipo di HWND nelle proprie bande. Per gestire questi casi, Automazione interfaccia utente supporta una forma alternativa di rilocazione HWND, come descritto nella sezione successiva.

Riposizionamento per i provider non WPF

I frammenti di automazione interfaccia utente possono contenere due o più elementi contenuti in una finestra (HWND). Poiché ogni HWND ha un proprio provider predefinito che considera HWND come figlio di un oggetto HWND contenente, l'albero di automazione interfaccia utente mostrerà, per impostazione predefinita, i HWND nel frammento come elementi figlio della finestra padre. Nella maggior parte dei casi questo comportamento è utile, ma talvolta può generare confusione perché non corrisponde alla struttura logica dell’interfaccia utente.

Un esempio valido è un controllo Rebar. Un controllo Rebar contiene bande, ognuna delle quali può contenere a sua volta un controllo basato su HWND come una barra degli strumenti, una casella di modifica o una casella combinata. Il provider di finestra predefinito per l'HWND del controllo Rebar vede gli elementi HWND delle bande come elementi figlio e il provider del controllo Rebar considera le bande come elementi figlio. Poiché il provider HWND e il provider del controllo Rebar operano in tandem e combinano i rispettivi elementi figlio, sia le bande che i controlli basati su HWND vengono visualizzati come elementi figlio del controllo Rebar. Dal punto di vista logico, tuttavia, solo le bande devono apparire come elementi figlio del controllo Rebar e ogni provider di banda dovrebbe essere abbinato al provider HWND predefinito per il controllo che contiene.

A tale scopo, il provider di radice del frammento per il controllo Rebar espone un set di elementi figlio che rappresentano le bande. A ogni banda corrisponde un unico provider che può esporre proprietà e pattern. Nella sua implementazione di HostRawElementProvider, il provider di bande restituisce il provider di finestra predefinito per il controllo HWND, ottenuto chiamando HostProviderFromHandlee passando l'handle della finestra del controllo. Infine, il provider di radice del frammento per il controllo Rebar implementa l'interfaccia IRawElementProviderHwndOverride e nella sua implementazione di GetOverrideProviderForHwnd restituisce il provider di bande appropriato per il controllo contenuto nell'HWND specificato.

Vedi anche