Implementing a Microsoft Active Accessibility (MSAA) Server Using the Windows API and C++
The oldest and simplest of the Accessibility APIs used in Microsoft Windows is Microsoft Active Accessibility or MSAA. This article provides a brief introduction on how to implement a MSAA Server using the Windows API and the C++ programming language.
The IAccessible interface
The heart of MSAA is the IAccessible interface. This interface exposes methods and properties that allow an accessibility server to make a user interface element and its children accessible to accessibility client applications. The methods and properties of the IAccessible interface allow a Windows API application to meet WCAG Success Criterion 4.1.2: Name, Role, Value, which requires that an accessibility client be able to programmatically determine the Name, Role, Value, and States of all user interface components (including but not limited to: form elements, links and components generated by scripts).
The following table provides information the methods of the IAccessible interface that are used to expose each of these properties.
Property | Method | ||
---|---|---|
Name | IAccessible::get_accName | |
Role | IAccessible::get_accRole | |
State | IAccessible::get_accState | |
Value | IAccessible::get_accValue |
See the IAccessible interface page for a complete list of the members of the interface and a detailed description of each method. The Content of Descriptive Properties page provides information on the expected value of these properties.
The Name, Role, and State properties are required for all user interface components that can gain focus. The Value property may be required for some user interface components but not for others. More information on which members of the IAccessible interface should be implemented for a given user interface component can be found in the Choosing Which Properties to Support page.
How an accessibility client obtains an IAccessible object
An accessibility client use one of the following functions to obtain an IAccessible object.
See the Getting an Accessible Object Interface Pointer page for more information on these functions.
What happens when an accessibility client requests an IAccessible object?
When an accessibility client requests an IAccessible object using the AccessibleObjectFromEvent, AccessibleObjectFromPoint, and AccessibleObjectFromWindow functions Microsoft Active Accessibility sends the WM_GETOBJECT message to the appropriate window procedure within the appropriate server application with the lParam parameter set to OBJID_CLIENT. Your Microsoft Active Accessibility (MSAA) server needs to handle this message.
Handling the WM_GETOBJECT Message
When your Microsoft Active Accessibility (MSAA) Server receives the WM_GETOBJECT message it should use the LresultFromObject function to convert an IAccessible object pointer to a LRESULT and return the resulting value.
There are three options for obtaining the IAccessible object pointer.
- Create New Accessible Objects
- Reuse Existing Pointers to Objects
- Create New Interfaces to the Same Object
The following code sample demonstrates the Reuse Existing Pointers to Objects technique.
(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
LRESULT OnGetObject{
if (static_cast<LONG>(lParam) != OBJID_CLIENT)
{
return DefWindowProcW(hWnd, message, wParam, lParam);
}
// Retrieve the control.
* pCustomList = GetControl(hWnd);
ContactListControlif (pCustomList == nullptr)
{
return 0;
}
// Create the accessible object.
* pAccServer = pCustomList->GetAccServer();
ContactListControlAccServerif (pAccServer == nullptr)
{
= new (std::nothrow) ContactListControlAccServer(hWnd, pCustomList);
pAccServer if (pAccServer == nullptr)
{
return 0;
}
->SetAccServer(pAccServer);
pCustomList->SetControlIsAlive(true);
pAccServer}
= LresultFromObject(
LRESULT Lresult , wParam,
IID_IAccessiblestatic_cast<IAccessible*>(pAccServer));
return Lresult;
}
The above code is from the Windows API Accessibility Server sample application.
For more information on handling the WM_GETOBJECT message see the following.
- Handling the WM_GETOBJECT Message
- How WM_GETOBJECT Works
- When to Respond to the WM_GETOBJECT Message
Events
Implementing the IAccessible interface is just one part of the puzzle. You also need to notify fire event notifications. This is done using the NotifyWinEvent function. See Event Constants, System-Level and Object-Level Events, and What Are WinEvents? for more information.
Additional Resources
Additional information can be found in the following locations.