Microsoft Active Accessibility (MSAA)
is the name that Microsoft has given to their implementation of assistive technologies (AT).
MSAA has been available as an add-on since Windows 95 and is
built into subsequent Windows releases. The most typical use of MSAA is to allow
to access UI elements in applications such as web browsers. However, MSAA
can be used by any Windows application, by simply linking to oleacc.dll
provides functions to easily retrieve accessibility information
from UI applications that support
and wraps the
This article does not discuss how to implement MSAA in an application.
If that is what you are interested in, you should read
Microsoft has just introduced a new assistive technology called
which is not covered in this article.
The demo app shows how XMSAALib
can be used.
The Start Event Handler button calls |
causes a hook function to be called when a window receives the focus - in this case,
when the Firefox address bar is clicked:
The hook function calls
AccessibleObjectFromEvent() and then
calls user-supplied callback function with
The callback function can then call any of the
to retrieve whatever information is necessary.
The Enum All Browser Objects button calls |
EnumAccessible() to iterate
IAccessible child objects of browser window
(the browser is selected by four radio buttons):
The child object information is shown in listbox, and is also written to a file
in XML format during enumeration - the button Display Object Tree
displays the resulting object tree using
I adapted code for
EnumAccessible() from this
The Get Browser Address Bar button retrieves the URL value currently
contained in the address (or location) bar:
The code to get address bar is another example of how to use
to enumerate child objects. To find address bar, we have to be aware of
how various browsers implement MSAA information for address bar object. The
following table shows this information for major browsers:
|Browser Address Bar Object Characteristics|
|Firefox 2||- ||editable text||http://www.codeproject.com/|
|Firefox 3||Location||editable text||http://www.codeproject.com/|
|Internet Explorer 6||Address||editable text||http://www.codeproject.com/|
|Internet Explorer 7||Address||editable text||http://www.codeproject.com/|
|Google Chrome 1.0||Location||editable text||http://www.codeproject.com/|
|Opera 9||- ||- ||- |
|Opera 10 alpha||- ||editable text||http://www.codeproject.com/|
|Safari 3||- ||- ||- |
Of the major browsers in use, Opera 9 and Safari 3 fail to provide address bar information
As the table shows, Opera has now implemented this in version 10. It is unknown whether
Apple plans to add this to Safari.
The key characteristics to look
for in the callback function is an object role of editable text. Next, the
object name can have one of three values: empty (or nameless), Location, and
Address. Finally, we look for the http URL specifier in the object value.
This approach allows us to query the current URL of most browsers.
MSAA Development Tools
The following two free tools
(both available from this web page
proved invaluable in exploring MSAA and creating XMSAALib
AccExplorer32 - this tool displays the object tree for any MSAA-enabled window.
First, click on the Build New Tree toolbar button:
Then drag the crosshairs over the window you want to explore:
When you release the
crosshairs, the object tree will be built and displayed:
You can then go to File | Save to save the object tree to a file.
Inspect32 - this tool dynamically displays the
when the cursor hovers over an MSAA-enabled window. In the screenshot below, the cursor
is over the Firefox 3 address bar:
Of these two tools, Inspect32 seems to have more stability problems,
so I usually close it after I have what I need.
Here are functions in
|BOOL EnumAccessible(HWND hwnd, XENUMACCESSIBLEPROC lpEnumAccessibleProc, LPARAM lParam)||Enumerates all child accessible objects via callback function specified by lpEnumAccessibleProc|
|HWND GetFirefoxHwnd()||Returns HWND of Firefox browser|
|HWND GetGoogleChromeHwnd()||Returns HWND of Google Chrome browser|
|HWND GetInternetExplorerHwnd()||Returns HWND of Internet Explorer browser|
|BOOL GetObjectChildCount(IAccessible *pAcc, long& nCount)||Retrieves the number of children that belong to this object|
|BOOL GetObjectDescription(IAccessible *pAcc, VARIANT *pvarChild, LPTSTR lpszDescription, UINT cchDescription)||Retrieves a string that describes the visual appearance of the specified object|
|BOOL GetObjectLocation(IAccessible *pAcc, VARIANT *pvarChild, RECT& rect)||Retrieves the specified object's current screen location|
|BOOL GetObjectName(IAccessible *pAcc, VARIANT *pvarChild, LPTSTR lpszName, UINT cchName)||Retrieves the name of the specified object|
|BOOL GetObjectRole(IAccessible *pAcc, VARIANT *pvarChild, UINT& nRole)||Retrieves information that describes the role of the specified object|
|BOOL GetObjectRoleString(IAccessible* pAcc, VARIANT* pvarChild, LPTSTR lpszBuf, UINT cchBuf)||Retrieves information (as a string) that describes the role of the specified object|
|BOOL GetObjectState(IAccessible* pAcc, VARIANT* pvarChild, UINT& nState)||Retrieves the current state of the specified object|
|BOOL GetObjectStateString(IAccessible* pAcc, VARIANT* pvarChild, LPTSTR lpszBuf, UINT cchBuf)||Retrieves the current state of the specified object (as a string)|
|BOOL GetObjectValue(IAccessible *pAcc, VARIANT *pvarChild, LPTSTR lpszValue, UINT cchValue)||Retrieves the value of the specified object|
|HWND GetOperaHwnd()||Returns HWND of Opera browser|
|BOOL StartGetObjectFromEvent(XWINEVENTURLPROC lpfnXWinEventUrlProc)||Starts event handler for object|
|void StopGetObjectFromEvent()||Stops event handler for object|
How To Use
CXMSAALib into your own program, you first need
to add following files to your project:
If you do not include stdafx.h in XMSAALib.cpp, then you must
mark XMSAALib.cpp as not using precompiled headers
in the project settings.
Next, include the header file XMSAALib.h in the module
where you want to call XMSAALib functions.
For more details on how to use, please see XMSAALibTestDlg.cpp.
CodeProject Articles Used/Referenced in this Article
Version 1.0 - 2009 February 10
This software is released into the public domain. You are free to use
it in any way you like, except that you may not sell this source code.
If you modify it or extend it, please to consider posting new code here
for everyone to share. This software is provided "as is" with no expressed
or implied warranty. I accept no liability for any damage or loss of
business that this software may cause.