Architecture and Key API Elements


This section contains information about the following topics.

VARIANT Structure

The VARIANT structure carries a wide variety of information used when calling functions through the IDispatch interface. For more information about how Active Accessibility uses the IDispatch interface, see IDispatch Interface. Since so many Active Accessibility API elements use IDispatch, you'll frequently work with VARIANT structures as well.

Essentially, the VARIANT structure is a container for a large union that can carry many types of data. Before using the structure, you must initialize it by calling the VariantInit OLE function.

The value in the first structure member, vt, describes which of the union members is valid. When you receive information in a VARIANT structure, check the vt member to find out which member to look at next. Similarly, when you send information using a VARIANT structure, always set vt to reflect the union member you're using to send the information.

For more information about the VARIANT structure, please refer to OLE Automation documentation.

IDispatch Interface

The IDispatch interface provides the tools that some developers need to work between C/C++ applications and Microsoft Visual Basic® applications. This interface essentially provides an indirect way to expose object methods and properties. The IDispatch method provides information about what methods an object supports, provides identifiers for those methods, and executes them on the caller's behalf if needed.

Many objects built on OLE expose the IDispatch interface to support OLE Automation. Server applications must support the IDispatch interface for this purpose. However, since C/C++ client developers need not interact with VB applications, they should use the IAccessible interface to achieve the best performance. Because most Active Accessibility API functions retrieve objects by way of their IDispatch interface, you'll often need to retrieve an IAccessible interface by calling the object's QueryInterface method and specifying the IID_IAccessible reference identifier as the iid parameter.

Oleacc.h defines the following DISPID values for use with the IDispatch interface.

// PROPERTIES: Hierarchical
#define DISPID_ACC_PARENT                   (-5000)
#define DISPID_ACC_CHILDCOUNT               (-5001)
#define DISPID_ACC_CHILD                    (-5002)
                                             
// PROPERTIES:  Descriptional
#define DISPID_ACC_NAME                     (-5003)
#define DISPID_ACC_VALUE                    (-5004)
#define DISPID_ACC_DESCRIPTION              (-5005)
#define DISPID_ACC_ROLE                     (-5006)
#define DISPID_ACC_STATE                    (-5007)
#define DISPID_ACC_HELP                     (-5008)
#define DISPID_ACC_HELPTOPIC                (-5009)
#define DISPID_ACC_KEYBOARDSHORTCUT         (-5010)
#define DISPID_ACC_FOCUS                    (-5011)
#define DISPID_ACC_SELECTION                (-5012)
#define DISPID_ACC_DEFAULTACTION            (-5013)

// METHODS
#define DISPID_ACC_SELECT                   (-5014)
#define DISPID_ACC_LOCATION                 (-5015)
#define DISPID_ACC_NAVIGATE                 (-5016)
#define DISPID_ACC_HITTEST                  (-5017)
#define DISPID_ACC_DODEFAULTACTION          (-5018)

For more information about the IDispatch interface, OLE Automation, and COM, see the references discussed in Where to Find More Information.

IAccessible Interface

The IAccessible interface represents an accessible object. Its methods allow client applications to examine object properties that describe the object, set and retrieve selection states, navigate to other objects, perform hit testing, and invoke an object's default action.

This section describes how you can work with accessible objects using the IAccessible interface. Additionally, this section introduces the concept of object navigation and presents the three navigation methods that the IAccessible interface provides. Information is divided into the following topics.

Querying an Object for its Properties

A client application can access all of an object's properties through the IAccessible interface. To retrieve an object property, you must first have the address of the object's IAccessible interface. Then, call the property's corresponding property access method (like IAccessible::get_accName) to retrieve the desired information.

All property access methods can access information for a container object and any simple elements it contains—it is the server's responsibility to maintain property information for simple elements.

For more information about object properties, see Properties for Accessible Objects.

Invoking an Object's Default Action

Applications can invoke an accessible object's default action by calling its IAccessible::accDoDefaultAction method. You can query for an object's DefaultAction property by calling the IAccessible::get_accDefaultAction method.

Effectively, calling accDoDefaultAction causes the object to perform its primary function. For example, calling accDoDefaultAction for a button control would cause the button to be pressed as though the user had clicked it.

Object Navigation

The term "navigation," when used in the context of accessible objects, refers to the process of retrieving the address of another object's IAccessible or IDispatch interface using the methods provided by the current object.

Hierarchical Object Navigation

Often, client applications must move between objects based on their parent-child relationships. For example, an accessibility aid might already have information about a toolbar control, but not yet know anything about the buttons or other controls contained within it.

The IAccessible interface exposes the hierarchical relationships between objects through the IAccessible::get_accParent and IAccessible::get_accChild methods. Using these methods, client applications can navigate from a parent object to its children or vice versa.

Spatial and Logical Object Navigation

Applications can retrieve information about an object that is spatially or logically near the current object by using the IAccessible::accNavigate method. Using this method, a client can navigate to another object based on its location on the screen (spatial) or to the object that logically precedes or follows the current object, as determined by the server (logical). The client application specifies the type and direction to navigate by using navigational constants when calling the method.

The two types of navigation are very different. Spatial navigation is simple in concept; if a client wants the object to the right of the current one, the server retrieves it and gives it to the client. However, since logical relationships between objects are subjective, logical navigation is less straightforward for both the client and server. Generally, these relationships parallel those in keyboard navigation. For example, imagine a typical dialog box that contains a few edit controls, an OK button and a Cancel button. In this case, calling the IAccessible::accNavigate method to move to the next or previous object in the dialog box is analogous to the user pressing TAB or SHIFT+TAB. That is, when the user presses TAB, the system moves focus to the next object, and when the user presses SHIFT+TAB, the system moves the focus to the previous object.

When performing spatial navigation, clients must be aware of all floating objects. Because a floating object isn't clipped to its parent, you can't be sure of the hierarchical relationship between two objects near one another on the screen.

The following illustration shows this example of a floating object that isn't clipped to its parent.

The Open common dialog box

Object Navigation Through Hit Testing

Applications can retrieve information about a child object by hit testing a point on the screen. To do this, call the current object's IAccessible::accHitTest method, passing the screen location to be hit tested in x- and y-coordinates. After the call, the pvarChild parameter points to a VARIANT structure that describes the hit test's result. If the call succeeds, the VARIANT structure's ppdispVal member is the address of the child object's IDispatch interface.

If multiple child objects overlap at a specified point, the accHitTest method retrieves the one that visually appears to occupy the space. However, accHitTest does not account for overlapping windows or clipping performed by the parent. Therefore, if a window covers a child object, hit testing the covered point will successfully retrieve the child object, even though it isn't actually visible at that point.

Additionally, the accHitTest method retrieves information about the topmost child object under the specified point. For example, if a child object displays a child of its own at the given point, only the top-level child object's information is returned.

Like any on-screen graphic, accessible objects can vary in shape. This isn't usually a problem, since most on-screen entities are well represented by rectangles. Rectangles can accurately describe most applications and their components: the application window, the menu, dialog boxes, buttons, scroll bars, and other common controls. As a result, accessible objects currently provide location information in terms of rectangles (by way of the IAccessible::accLocation method). If an object isn't shaped like a rectangle, the accLocation method provides the rectangle that contains the object.

Occasionally, rectangles aren't accurate enough. Accessible objects support the IAccessible::accHitTest method to provide access to clients on a pixel-by-pixel basis. This comes in handy when your application is tracking the location of the mouse pointer to gather information. The following illustration shows the relationship between an eccentric object's region and its bounding rectangle.

Illustration of an object's region versus its rectangle

Accessible Object Properties

Accessible objects maintain several pieces of information, called "properties," that help describe the object's appearance, nature, and purpose. The IAccessible interface extends methods allowing an application to retrieve these properties. The application can examine the properties, determine what is valuable to the user, and convey information to the user as needed.

This section discusses the properties in detail, providing a conceptual overview for each. The following topics are covered.

You can access each property from C/C++ or Visual Basic® applications. These descriptions examine the properties from a C/C++ perspective.

Name Property

The Name property, retrieved by calling the IAccessible::get_accName method, is a string used by accessibility aids to identify, find, or announce an object for the user. For example, the text on a button control is its name, while the name for a list box or edit control is the text from an associated static text control. Even graphics objects or owner-draw controls that don't display a name should maintain text to provide when queried for the Name property.

It is the server's task to make object names as intuitive as possible. Additionally, the server must make an object's Name property unique relative to any sibling objects in the parent container. This allows accessibility aids (clients) to narrow the object's meaning or purpose more easily.

Navigation within tables presents especially difficult problems for some users. Therefore, server applications should use table cell names that are as descriptive as possible. For example, a server could name a cell by combining the names of the rows and columns it occupies. These can be like "A1," but it is generally more descriptive to use row and column names when available, such as "Tom, February."

Servers, by way of the IAccessible::put_accName method, can allow the client to set an object's name. Servers can choose to assist users by allowing them to assign unique and persistent names for objects. This allows the user to tag objects with names that they use to easily return their focus to the object later. A server must provide its own storage for persistent names. If a server doesn't support the IAccessible::put_accName method, it fails the call by returning S_FALSE.

If an object does not have access to its Name property it should delegate requests to its parent, identifying itself by its child ID. For example, if a client asks an edit control for its name, the edit control will probably delegate the query to its parent, which would return the value of the static text control that labels the edit control. In other cases, the child object might be able to retrieve the text itself. However, the server must be careful to ensure that a parent and child do not each delegate calls to each other.

Role Property

The Role property, retrieved by calling the IAccessible::get_accRole method, describes an object's role. Generally, the Role property describes the object's purpose in terms of its relationship with sibling or child objects. The oleacc.dll dynamic link library supports the role constants defined in the oleacc.h header file. These role constants are symbolic numeric values that identify common object roles. However, servers can provide strings when the standard values do not suffice. Use the GetRoleText method to retrieve these strings.

In many cases, the object's role is obvious; windows have a role of ROLE_SYSTEM_WINDOW and buttons have the ROLE_SYSTEM_PUSHBUTTON role. However, some objects' roles aren't so easy to describe. A folder's large-icon view allows arbitrary arrangement of icons, so its role could be described as ROLE_SYSTEM_GROUPING. Or, a control that provides items in fixed rows and columns could be have the ROLE_SYSTEM_TABLE role.

State Property

The State property, retrieved by calling the IAccessible::get_accState method, describes an object's status at a moment in time. In most cases, the retrieved value is a bitmask containing one or more of the object state constant flag values, but the server can provide a string if none of the predefined flags suffice. Use the GetStateText method to retrieve these strings. The oleacc.dll dynamic-link library supports these object state constants, which are defined in the oleacc.h header file.

Servers can combine the predefined flags with an "alert level" that indicates the importance of the other flags. These are STATE_SYSTEM_ALERT_LOW, STATE_SYSTEM_ALERT_MEDIUM, and STATE_SYSTEM_ALERT_HIGH. A client can use these alert levels to gauge the information's urgency.

Value Property

The Value property, retrieved by calling the IAccessible::get_accValue method, represents visual information contained by the object or conveys hierarchical information. In most cases, the Value property is used to tell the client about what visual information an object contains. For example, the value for an edit control is the text it contains, but a menu item has no value.

In the case of a tree view control, the Value property provides hierarchical information. The tree view control itself has no Value property, but each item within the control has a zero-based value that represents its level within the hierarchy. Top-level items have a value of 0, second-level items have a value of 1, and so on.

Servers, by way of the IAccessible::put_accValue method, can allow the client to set an object's value. This could be useful if a voice input device or other accessibility aid is trying to let the user easily change the value in an object, like an edit control. If a server doesn't support the IAccessible::put_accValue method, it fails the call by returning S_FALSE.

Description Property

An object's Description property, retrieved by calling the IAccessible::get_accDescription method, provides a textual description for an object's visual appearance. The description is primarily used to provide greater context for low-vision or blind users, but can also be used for context searching or other applications.

All objects should have a description, except in cases where the description is obvious or redundant based on the object's Name, Role, State, and Value properties. A button with the word "OK" does not need additional description, but all graphical objects and controls must have some.

For example, imagine a toolbar containing a button that shows a picture of a cactus. The button's properties describe its role, name, purpose, and so on, but the Description property conveys information that is less tangible, like "A button that shows a picture of a cactus."

Not all objects support the Description property; if the call to get_accDescription returns the DISP_E_MEMBERNOTFOUND value, then no object description is available.

Focus Property

An object's Focus property, retrieved by calling the IAccessible::get_accFocus method, allows clients to discover if a particular accessible object and/or child element has the focus.

Like many elements in Windows applications, accessible objects can be selected and receive keyboard focus. These attributes enable users to interact with application elements, changing values or otherwise manipulating them.

Note that object selection and object focus are two entirely different ideas. The "focused" object is the one object in the entire system that receives keyboard input, while the "selected" object is marked to participate in some type of group operation. Additionally, focused items can be in or out of a selection of items. For example, you can select several items in a list view control in preparation for moving or deleting them all. However, the focus is given only to one object in the system at a time.

Note that menus do not incorporate item selection. When a user highlights menu items, the server must not generate EVENT_OBJECT_SELECTION events or any other selection related event. Instead, the server should generate an EVENT_OBJECT_FOCUS event specific to the object that is currently highlighted. This only applies to a server creating custom menu code or a user interface that appears to the user as a menu. Active Accessibility provides support for the Win32 menu APIs. Menus created via Win32 APIs and resource files will send the correct events and expose MSAA objects.

Note to implementers: If the object itself has the keyboard focus, return CHILDID_SELF as a VT_I4 type. If a child is an accessible object and has the focus, return the address of its IDispatch interface (a VT_DISPATCH type). Or, if a child has the focus but isn't an accessible object, return the child ID to the child as a VT_I4 type.

Selection Property

An object's Selection property, retrieved by calling the IAccessible::get_accSelection method, allows clients to discover which children within an accessible object are selected.

Like many elements in Windows applications, accessible objects can be selected and receive keyboard focus. These attributes enable users to interact with application elements, changing values or otherwise manipulating them.

Note that object selection and object focus are two entirely different ideas. The "focused" object is the one object in the entire system that receives keyboard input, while the "selected" object is marked to participate in some type of group operation. Additionally, focused items can be in or out of a selection of items. For example, you can select several items in a list view control in preparation for moving or deleting them all. However, the focus is given only to one object in the system at a time.

Note that menus do not incorporate item selection. When a user highlights menu items, the server must not generate EVENT_OBJECT_SELECTION events or any other selection related event. Instead, the server should generate an EVENT_OBJECT_FOCUS event specific to the object that is currently highlighted. This only applies to server creating custom menu code or a user interface that appears to the user as a menu. Active Accessibility provides support for the Win32 menus APIs. Menus created via Win32 APIs and Resource Files will send the correct events and expose MSAA objects.

Note to implementers: If the object has no children, but is itself selected, set the vt member to VT_I4 and lVal to CHILDID_SELF. If no child is selected, set vt to VT_EMPTY. If multiple children are selected, set vt to VT_UNKNOWN and punkVal to the IUnknown interface pointer of an object that can be used to enumerate the child objects. This object must support the IEnumVARIANT interface.

DefaultAction Property

An object's DefaultAction property, retrieved by calling the IAccessible::get_accDefaultAction method, describes its primary method of manipulation from the user's viewpoint. Do not confuse the DefaultAction property with the object's Value property. Some controls, such as an edit field, might have a value but not a default action. The following list provides some common examples.

The DefaultAction property is primarily for use by voice input and blind access utilities. For example, when a blind access utility encounters a custom control that it does not recognize, it can still provide a significant amount of information to the blind user, such as the object's name (like "Speed"), its role (like "Switch"), its default action, if supported (like "Adjust"), and the current value (like "High"). Of course, the client can also use OLE Automation to enumerate all the properties and methods that the object supports, but there could be very many and most can be obscure, so the DefaultAction property provides a simple method of succinctly conveying the operation that the user will most likely use.

Not all objects support the DefaultAction property; if the call to get_accDefaultAction returns the DISP_E_MEMBERNOTFOUND value, then the object has no default action. For example, objects that don't perform actions, like static text, won't have a default action.

Location Property

The Location property, retrieved by calling the IAccessible::accLocation method, can provide information that tells the user about the object's function. For example, the Location property for a toolbar button would be the object's bounding rectangle. If the object is a region, then this method returns the biggest rectangle encompassing the entire region.

Note to implementers: This method must not fail for visual objects. Currently, the only nonvisual objects are sound objects.

Help Property

The Help property, retrieved by calling the IAccessible::get_accHelp method, can provide information that tells the user about the object's function. For example, the Help property for a toolbar button that shows a printer might be, "Prints the current document." This text is not always unique within the user interface; it acts purely to elaborate on the object's purpose and what actions it might perform.

Not all objects support the Help property; if the call to get_accHelp returns the DISP_E_MEMBERNOTFOUND value, then the object does not support this property.

HelpTopic Property

The HelpTopic property, retrieved by calling the IAccessible::get_accHelpTopic method, retrieves details about a Help file that provides information about an object. This is provided in the form of a string that represents the path to the Help file and a value identifying the topic of interest.

The retrieved values can be used with the Win32 WinHelp function to display a help topic associated with the object.

The path name retrieved might be a network path (like "\\network\share\directory\filename.ext") or a Uniform Resource Locator (URL) to an Internet resource (like "http://www.microsoft.com/enable/helpfile.htm").

See the Windows® 95 SDK documentation on parsing paths for more information.

KeyboardShortcut Property

The KeyboardShortcut property, retrieved by calling the IAccessible::get_accKeyboardShortcut method, describes a key or key combination that will activate a given accessible object.

This shortcut key string can describe "shortcut keys" or "access keys." Each is described in the following list.
Term Description
Shortcut keys Key combinations that invoke an action. For example, CTRL + O is often used to invoke the Open file common dialog box.
Access keys Single keys, usually shown underlined in a drop-down menu or dialog box, that invoke an action when pressed. For example, if a user activates an application's File menu, the O key often invokes the Open file common dialog box. Access keys are usually only available when the container (like a menu) has keyboard focus.

The KeyboardShortcut property reflects shortcuts as the key or keys the user must press when the object has keyboard focus. For example, the Print menu command might have both a shortcut key (CTRL+P) and an access key (P). If the user presses CTRL+P while the menu is active, nothing happens, but pressing P invokes the application's Print dialog box. In this case, the KeyboardShortcut property is "P," to reflect what the user must press when the menu is active and has keyboard focus. This "shortcut by focus" type of philosophy is true for all accessible objects.

Active Accessibility describes key combinations using strings that fit a standard format, allowing utilities to parse them. The format is defined as [modifier key +][...] + key-name. For example: "ALT+F", "CTRL+ALT+4", "WIN+F1", "BACKSPACE", or "CTRL+ALT+SHIFT+BACKSPACE".

The modifier keys are:
Modifier key Description
ALT Alternate modifier key
CTRL Control modifier key
SHIFT Shift modifier key
WIN Windows Logo key
FN Function key on portable computers

The server never localizes keyboard shortcut strings. If an accessibility aid enunciates keyboard shortcuts to the user, it can parse them into separate key names and substitute localized names. This functionality would be useful, for example, in a blind access utility reading keyboard shortcuts to the user at the user's request.

Accessible Object Methods

Accessible objects maintain several ways to get information from an object, called "methods," that help communicate the object's appearance, nature, and purpose. The IAccessible interface extends methods allowing an application to retrieve this information about the object.

This section discusses the methods in detail, providing a conceptual overview for each. The following topics are covered.

You can access each property from C/C++ or Visual Basic® applications. These descriptions examine the properties from a C/C++ perspective.

IAccessible::accSelect Method

The Select method, accessed by calling the IAccessible::accSelect method, modifies the selection or moves the keyboard focus according to the specified flags.

This parameter can be the child ID value (provided by the object), CHILDID_SELF for the object itself, or a string identifying the child (such as "A1").

This method returns S_OK if successful or one of the following values or a standard COM error code otherwise.
DISP_E_MEMBERNOTFOUND
E_INVALIDARG
S_FALSE

IAccessible::accNavigate Method

The Navigate method, accessed by calling the IAccessible::accNavigate method, retrieves the next or previous sibling or child object in a specified direction.

This method returns S_OK if successful or one of the following values or a standard COM error code otherwise.
DISP_E_MEMBERNOTFOUND
E_INVALIDARG
S_FALSE

This method retrieves only objects that have a defined screen location. However, the object might be currently clipped or obscured by another object. This method does not change selection or focus. To change focus to or select an object, use the IAccessible::accSelect method. For more information, see Object Navigation.

The NAVDIR_NEXT and NAVDIR_PREVIOUS values will not cause looping. The method will fail, returning S_FALSE, after the last or first object is found.

Note to implementers: If the current object does not have any knowledge of peer objects, it should ask its parent object to perform the navigation. If the current object does not have any knowledge of its parent, it should return S_FALSE.

Active Accessibility do not always support navigation to invisible children. Remember that it is OK for an object to support the IAccessible::accNavigate and IAccessible::get_accChild methods for children that are invisible, but that clients cannot expect this. In the section where the proxies are implemented, that menus, menu items, and menu popups allow navigation to invisible children, but that other objects we create proxies for do not. You might not be able to navigate to all of an object's children, if they have the flag STATE_SYSTEM_INVISIBLE

IAccessible::accHitTest Method

The HitTest method, accessed by calling the IAccessible::accHitTest method, retrieves the IDispatch interface pointer of a child object at a given point on the screen.

This method returns S_OK if successful or a standard COM error code otherwise.

When this method is used in certain situations, additional usage notes apply. For more information, see Object Navigation.

Note to implementers: This method must not fail for visual objects. Instead, set the vt member of the VARIANT structure to VT_EMPTY. Currently, the only nonvisual objects are sound objects.

IAccessible::accDoDefaultAction Method

The DoDefaultAction method, accessed by calling the IAccessible::accDoDefaultAction method, performs the object's default action.

This method returns S_OK if successful or one of the following values or a standard COM error code otherwise.
DISP_E_MEMBERNOTFOUND
E_INVALIDARG

You can retrieve the object's DefaultAction method by using the IAccessible::get_accDefaultAction method.

Only controls that perform actions support IAccessible::accDoDefaultAction. Some controls, like edit fields, can have a primary value but not a primary action.

In most cases, the client could also perform this action using standard OLE Automation, as well as carry out any nondefault actions supported by the object. However, this method provides an easy way to identify and perform an object's most commonly used function. Also, with the information provided by the IAccessible::get_accDefaultAction method, you can describe the action to the user even if the application does not ship an OLE Automation type library.

WinEvents

This section contains information about events generated by accessible objects. The following topics are covered.

What Are WinEvents?

Server applications use "WinEvents" to notify clients about specific operations they perform. Accessible objects send these event notifications by using the NotifyWinEvent function. This function essentially tells Active Accessibility that a specific event occurred, which object the event is associated with, and specifies the child element if necessary. When Active Accessibility is notified, it calls any hook procedure functions that were registered for that event.

Client applications register callback hook procedure functions for these events by using the SetWinEventHook function. Applications can set a single hook function for all possible events, or multiple hooks for discrete ranges of events. Once called, the callback function receives several parameters describing an object, as well as an event constant value identifying the event that the specified object generated. Active Accessibility provides several options for callback functions; for more information, see About the WinEventProc Callback Function.

Note that WinEvents only notify clients that an event is occurring or has occurred—clients cannot fail them.

Who Generates Which Events?

There are two classes of events, system level and object level, each with a corresponding event constant value. System-level events describe situations affecting all applications in the system, whereas object-level events pertain to situations specific to an object or objects within one application. System-level event values are macro values whose labels begin with EVENT_SYSTEM; object-level event values begin with EVENT_OBJECT.

Server applications and the operating system both generate WinEvents. The operating system generates both system- and object-level events for systemwide notifications about focus changes, activation changes, system alerts, or for events regarding system objects like common controls. Server applications typically generate object-level events regarding the accessible objects they contain, notifying clients about object creation, destruction, selection, or other object-level events. Remember that the server application should minimize sending redundant messages.

In some cases, server applications will send system-level events. For example, when an application displays a message box by calling the MessageBox Win32 function, the system generates the EVENT_SYSTEM_ALERT system-level event. However, if a server application displays an alert box on its own (without calling MessageBox) it should generate an EVENT_SYSTEM_ALERT event on behalf of the custom window.

About the WinEventProc Callback Function

The WinEventProc callback function is the starting point for most client activity. Active Accessibility calls this hook procedure in response to specific ranges of events that server applications generate. You specify which events a hook procedure is called for when you register it with the SetWinEventHook function.

WinEventProc receives seven parameters. The first, hWinEventHook, is an identifier for the hook procedure, and is provided for reference—you won't usually do anything with it. The second parameter, event, is one of the event constants that describes the type of event that occurred. The next three parameters, hwnd, idObject, and idChild, combine to tell you about the window, object, and possible child element that generated the event. The following table provides additional explanation for these three parameters.
Parameter name Description
hwnd Handle to the window where the event originated.
idObject Object identifier of the object associated with the event. This is one of the object constants, and is set to OBJID_WINDOW if the window itself generated the event.
idChild Identifier of the child element that generated the event. This is CHILDID_SELF if no child element generated the event.

Generally, a client does little more with these three parameters than use them in an object retrieval call, such as the AccessibleObjectFromEvent function. For more information about identifiers, see Object and Child Identifiers.

The remaining two parameters, idEventThread and dwmsEventTime, provide background information about the thread associated with the event and the time the event occurred.

In-context and Out-of-context Hook Procedures

There are two types of hook procedures, in-context and out-of-context. These terms describe the WinEventProc callback function's memory location relative to the server's address space. An in-context hook procedure is located in a dynamic-link library (DLL) that Active Accessibility maps into the server's address space. Similarly, an out-of-context hook procedure is located in the client's address space, whether it's in the code body or in a DLL.

In-context callbacks receive event notifications synchronously from the server, while out-of-context callbacks receive asynchronous event notifications. As a result, in-context callbacks tend to be very fast, since processing occurs in the server's address space, requiring no marshaling across process boundaries. NOTE: For greatest performance, use In-Context Event Notification and access object properties within the same address space of the object. When using in-context callbacks, client developers must ensure that the provided function doesn't use a lot of processor time, since the server must wait for the callback to return before it can continue.

Since out-of-context callbacks aren't mapped into the server's address space, Active Accessibility marshals across process boundaries, making event notifications asynchronous and causing responses noticeably slower than in-context callbacks. Although the event notifications are asynchronous, Active Accessibility assures that the callback function receives all events in the order they were generated.

Multiple Hook Procedures

You can register multiple hooks to respond to various ranges of events. Therefore, the callback function's label doesn't necessarily need to be "WinEventProc"—it can be anything you want, so long as its argument list and return value are identical to the function declaration for the WinEventProc function.

About the Client-Server Event Process

The client-server event process describes the method by which Active Accessibility enables client applications to establish a direct connection to an accessible object in response to events that the object generated. This process is a bit like a matchmaker setting up a date for two people who don't know each other. For example, the matchmaker has a friend who expressed an interest in dating, and the matchmaker knows another friend who might be compatible. The matchmaker tells both people about each other, handles the initial exchange of phone numbers, and then lets the two arrange a first date on their own. In this analogy, Active Accessibility plays the role of the matchmaker, the server application is the friend who wanted a date, and the client application is the potential match.

This general concept holds true for the client-server event process. When it calls the NotifyWinEvent function, the server application tells Active Accessibility about events it has generated. Active Accessibility checks if any client applications have registered a WinEvent hook and sends the event notification to an appropriate callback procedure. If the client application is interested in the event, it can request access to the generating object by using AccessibleObjectFromEvent, or another accessible object retrieval function. This is the beginning of the so-called "exchange of phone numbers" phase.

When the client calls AccessibleObjectFromEvent, Active Accessibility sends the server application a WM_GETOBJECT message. In response to WM_GETOBJECT, the server application returns a value that acts as a one-time reference to the object that generated the event. Active Accessibility uses this reference to retrieve the address of an object interface such as IAccessible or IDispatch, and gives that address to the client application. Once it has an interface address, the client can directly contact the accessible object to manipulate it or retrieve information as needed.

Verifying Events

If your client application uses asynchronous event hooks (when the hook callback function is in your process and not the server's), it is possible that the window associated with an event no longer exists at the time the hook procedure is called. Therefore, you must verify that the window associated with an event still exists before taking any other action related to the event. To ensure that a window still exists, use the Win32 IsWindow function.

For more information about synchronous and asynchronous event hooks, see About the WinEventProc Callback Function.

WinEvents for Simple Elements

Often, simple elements can generate events. Since these elements are not accessible objects and don't support Active Accessibility, they present a special problem for accessibility aids. Therefore, Active Accessibility places the responsibility of supporting the IAccessible interface on the element's parent object. With every event notification, the client application's WinEventProc hook procedure receives a child identifier in the idChild parameter, which specifies the simple element that generated the event. The accessible object that contains the element supports IAccessible on the child element's behalf. To access information about the child element, specify the child identifier in whatever method you call. If no child is associated with the event, idChild is CHILDID_SELF. For more information, see Object and Child Identifiers. All pertinent IAccessible methods accept the pvarChild parameter specifically for the purpose of finding child objects.

Alerts

Server applications generate the EVENT_SYSTEM_ALERT event to notify accessibility aids that a user interface change has occurred that a user might need knowledge of.

Before Active Accessibility, when an application changed an icon's appearance, accessibility aids had to decide whether or not to inform the user, without a clear idea about the information that the application was presenting. Was the information urgent enough that user's work should be interrupted? Was it moderately important information that the user should be informed about without being interrupted? Or, was it low-priority information that the user could choose to accept or ignore based on preference settings? Now, with Active Accessibility, the accessible object conveys urgency by using object state bits that the client can retrieve by calling the IAccessible::get_accState method.

A visual change normally triggers more than one event. For example, an accessible object generates the EVENT_OBJECT_VALUECHANGE event when its value string changes, and can optionally generate an accompanying EVENT_SYSTEM_ALERT event to indicate to the client that some priority level applies to the previous event.

For more information, see Event Constants and Object State Constants.

Changes to USER

Active Accessibility changes some core operating system components. In the case of Windows 95®, user.exe and user32.dll have been replaced with slightly modified versions to support WinEvents and other accessibility enhancements.

Additionally, USER is now sensitive to screen reader applications. When USER notices that the SPI_GETSCREENREADER bit is on, it changes its behavior as follows:

Display Device Interface Redirection

Active Accessibility exposes system graphics events through display device interface (DDI) redirection. This functionality allows applications to intercept graphics events before they affect the display device. Client applications that hook these events can examine or modify stack parameters related to specific DDI calls, failing the calls if they are unwanted.

About DDI Redirection

Client applications can set a DDI hook by using the SetDDIHook function. This function accepts parameters that describe the hook class, the location of the hook procedure, and private data that will be sent to the hook procedure when a DDI function call occurs. All of an application's DDI hook procedures must be written in a 16-bit DLL.

The hook class describes the type of application that owns the DDI hook procedure. Active Accessibility uses this class to determine the order in which it calls the registered hook procedures. Hook classes are defined in winddi.h and are called in the following descending order. This is because each step depends on what the DDI function's screen changes.
Class Description
DDIHOOK_RECORDER Screen readers and screen capture utilities.
DDIHOOK_REMOTE Remoting utilities.
DDIHOOK_FONTS Font enhancers.
DDIHOOK_MAGNIFIER Screen magnifiers.

If multiple hooks are registered for a given class, Active Accessibility still uses the preceding order, but sends event notifications within a class to the most recently registered hook procedures first.

When Active Accessibility calls a DDI hook procedure, it receives parameters describing the DDI hook instance, the type of DDI function being called, and the address of a DDI stack structure. DDI stack structures, defined in winddi.h, are the parameters being passed to the specified DDI function as they exist on the stack. The hook procedure can examine these values, change them if necessary, and pass the event by calling the CallNextDDI function and using that return value as its own return. This function returns control to Active Accessibility, which sends event notifications to other registered hook procedures, finally calling the DDI function when all hook procedures have been notified and have passed the call. If a callback procedure changes a stack value, the new value will be reflected by any subsequent DDI hook procedures. If a hook procedure doesn't call CallNextDDI, the DDI function fails and never reaches the display device.

Setting a DDI Hook

You can set a DDI hook procedure by calling the SetDDIHook function. This function accepts five parameters. The first, hdcHook, is unused and must be set to NULL. The second parameter, hModCode, is a handle to the module that contains the hook procedure. This module must be a 16-bit DLL. Use the GetModuleHandle Win32 function to retrieve the module handle. The third parameter, lPrivateData, accepts a 32-bit value that will be passed to the hook procedure when an event occurs. The fourth parameter, hookClass, describes the type of application that the hook procedure belongs to. The last parameter, lpfnDdiHook, is the address of the hook procedure that Active Accessibility calls in response to DDI events.

The SetDDIHook function returns an HDDI value. This value is provided to identify the event hook and acts as the handle accepted when unhooking the event hook. For more information, see Unhooking a DDI Hook.

Unhooking a DDI Hook

When your application no longer needs a DDI hook, you can call the UnhookDDIHook function to remove it. This function accepts a single parameter, hddi, that identifies the event hook that will be removed. This value is returned when the hook was set by calling the SetDDIHook function. For more information, see Setting a DDI Hook.

Simulating Input

Applications can use Active Accessibility's SendInput function to simulate an uninterrupted series of user input events. SendInput provides the same functionality as the mouse_event, keyboard_event, and hardware_event Win32 functions. The SendInput function accepts three parameters. The first parameter, cInputs, indicates the number of input events that will be simulated. The second parameter, rgInputs, is the base address of an array of INPUT structures, each describing a type of input event and additional information about that event. The last parameter, cbSize, accepts the size of the INPUT structure, in bytes.

SendInput works by injecting a series of simulated input events into a device's input stream. The effect is similar to calling the keybd_event or mouse_event Win32 functions repeatedly, except that the application ensures that no other input events intermingle with the simulated events. When the call completes, the return value indicates the number of input events successfully played to the system. If this value is zero, then input was blocked.

The SendInput function does not reset the keyboard's current state. Therefore, if the user has any keys pressed when you call this function, they might interfere with the events that this function generates. If you are concerned about possible interference, check the keyboard's state with the GetAsyncKeyState Win32 function and correct as necessary.

© 1997 Microsoft Corporation. All rights reserved. Legal Notices.