Share via


Implementing Server-side UI Automation Providers

This section describes how to implement a server-side UI Automation provider in Microsoft Win32.

Provider Interfaces

Custom controls provide support for UI Automation through providers that implement interfaces. Every provider must implement at least IRawElementProviderSimple. Providers for elements within a fragment (a complex control usually hosted in a single HWND) must implement IRawElementProviderFragment, and the provider for the top-level element in the fragment must implement IRawElementProviderFragmentRoot. Note that these interfaces do not inherit from one another. In addition, the provider must implement the appropriate interface for any control patterns it supports.

Optionally, a provider can implement IRawElementProviderAdviseEvents, which enables it to track request for events.

Finally, the IRawElementProviderHwndOverride interface enables repositioning of window-based elements within the UI Automation tree of a fragment. Most providers do not need to implement this interface.

Exposing the Provider

To make the UI Automation provider available to the application that uses the custom control, the control must respond to a WM_GETOBJECT message sent to its window by returning the object that implements IRawElementProviderSimple. For fragments, this must be the provider for the fragment root.

Providing Property Values

The provider's implementation of IRawElementProviderSimple::GetPropertyValue provides or overrides UI Automation property values.

For elements that are hosted in windows (HWNDs), UI Automation can retrieve some properties from the default window provider, but must obtain others from the custom provider.

Properties are identified by PROPERTYID types, which are obtained from GUIDs by using the UiaLookupId function. For a list of all property GUIDs, see PROPERTYID GUIDS.

Providers for HWND-hosted controls do not usually need to provide the properties identified by the following GUIDs:

  • BoundingRectangle_Property_GUID
  • ClickablePoint_Property_GUID
  • ProcessId_Property_GUID
  • ClassName_Property_GUID
  • HasKeyboardFocus_Property_GUID
  • IsEnabled_Property_GUID
  • IsKeyboardFocusable_Property_GUID
  • IsPassword_Property_GUID
  • Name_Property_GUID
  • RuntimeId_Property_GUID

The RuntimeId property of a simple element or fragment root hosted in a window is obtained from the window; however, fragment elements below the root (such as list items in a list box) must provide their own identifiers.

The IsKeyboardFocusable property should be returned for providers hosted in a Windows Forms control. In this case, the default window provider might be unable to retrieve the correct value.

The Name property is usually supplied by the host window provider. If a control is labeled, the Name might be taken from the label.

Control Patterns

UI Automation client applications can obtain control pattern objects from UI elements. Through these objects, they receive type-specific information about the control, and enable the user to interact with the control.

Providers support control patterns by implementing interfaces that are appropriate to the control type. For example, the provider for a button control must implement IInvokeProvider. A pointer to the object that implements this interface (it may be same object that implements IRawElementProviderSimple) is returned by IRawElementProviderSimple::GetPatternProvider.

For information about what control patterns should be supported for each type of control, and how they should be implemented, see UI Automation Control Patterns and UI Automation Control Types in the documentation for managed code implementations.

Events

UI Automation providers should raise events to notify client applications of changes in the state of the UI. The following functions are used to raise events.

Function Description
UiaRaiseAutomationEvent Raises various events, including events triggered by control patterns.
UiaRaiseAutomationPropertyChangedEvent Raises an event when a UI Automation property has changed.
UiaRaiseStructureChangedEvent Raises an event when the structure of the UI Automation tree has changed; for example, by the removal or addition of an element.

The purpose of an event is to notify the client of something taking place in the UI, whether the activity is triggered by the UI Automation system itself. For example, the event identified by Invoke_InvokedEvent_GUID should be raised whenever the control is invoked, either through direct user input or by the client application through the control pattern.

To optimize performance, a provider can selectively raise events, or raise no events at all if no client application is registered to receive them.

To ascertain whether any client applications have subscribed to any events, call the UiaClientsAreListening function.

For more precise information about what events are of interest to clients, implement the IRawElementProviderAdviseEvents interface in your provider object. The methods of this interface will be called whenever a client subscribes or unsubscribes to an event.

Provider Navigation

Providers for simple controls such as a custom button hosted in a window (HWND) do not need to support navigation within the UI Automation tree. Navigation to and from the element is handled by the default provider for the host window, which is specified in the implementation of IRawElementProviderSimple::HostRawElementProvider. When you implement a provider for a complex custom control, however, you must support navigation between the root node of the fragment and its descendants, and between sibling nodes.

Providers for elements of a fragment must support navigation within the fragment. The fragment root supports navigation to its children (but not to its parent or siblings; as with a simple element, this is handled by the default window provider). Descendants support navigation back to the parent, to their next and previous siblings, and to any children they may have. Elements other than the fragment root must return NULL from IRawElementProviderSimple::HostRawElementProvider, because they are not directly hosted in window.

The structure of a fragment is determined by your implementation of IRawElementProviderFragment::Navigate. For each possible direction from each fragment, this method returns the provider object for the element in that direction. If there is no element in that direction, the method returns NULL.

For example, a list box returns the provider for the first item in the list when the direction is NavigateDirection_FirstChild, and the provider for the last item when the direction is NavigateDirection_LastChild. Each list item returns the appropriate provider when the direction is NavigateDirection_Parent, NavigateDirection_NextSibling, or NavigateDirection_PreviousSibling. For directions that are not valid, elements return NULL.

Provider Reparenting

UI Automation fragments may contain two or more elements that are each contained in a window (HWND). Because each HWND has its own default provider that considers the HWND to be a child of a containing HWND such as the application window or a dialog box, the UI Automation tree will, by default, show the HWNDs in the fragment as siblings rather than in a parent-child relationship.

To reposition an HWND-hosted element in a fragment so that it appears as a child of the root element, you must override the default provider. To do so, implement IRawElementProviderHwndOverride. When IRawElementProviderHwndOverride::GetOverrideProviderForHwnd is called for the child element's HWND, return your custom provider for that element.