Click here to Skip to main content
Click here to Skip to main content

XMSAALib - a non-MFC class to retrieve accessibility (MSAA) info

, 10 Feb 2009
Rate this:
Please Sign up or sign in to vote.
XMSAALib provides APIs that allow you to retrieve MSAA (accessibility) information from a window by using the IAccessible interface. The demo app shows how to build an accessibility object tree from a window.

Introduction

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 screen readers 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, and using IAccessible COM interface. XMSAALib provides functions to easily retrieve accessibility information from UI applications that support IAccessible, and wraps the get_accXXXX IAccessible functions.

This article does not discuss how to implement MSAA in an application. If that is what you are interested in, you should read this article.

Microsoft has just introduced a new assistive technology called UI Automation (UIA) which is not covered in this article.

Demo App

The demo app shows how XMSAALib can be used.

screenshot The Start Event Handler button calls SetWinEventHook(), which causes a hook function to be called when a window receives the focus - in this case, when the Firefox address bar is clicked:

screenshot

The hook function calls AccessibleObjectFromEvent() and then calls user-supplied callback function with IAccessible pointer. The callback function can then call any of the IAccessible functions to retrieve whatever information is necessary.

screenshot The Enum All Browser Objects button calls EnumAccessible() to iterate through all IAccessible child objects of browser window (the browser is selected by four radio buttons):

screenshot

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 XHtmlTree:

screenshot

I adapted code for EnumAccessible() from this MSDN article.

screenshot The Get Browser Address Bar button retrieves the URL value currently contained in the address (or location) bar:

screenshot

The code to get address bar is another example of how to use EnumAccessible() 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
Browser Name Role Value
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 via IAccessible. 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:
  1. AccExplorer32 - this tool displays the object tree for any MSAA-enabled window.

    First, click on the Build New Tree toolbar button:

    screenshot

    Then drag the crosshairs over the window you want to explore:

    screenshot

    When you release the crosshairs, the object tree will be built and displayed:

    screenshot

    You can then go to File | Save to save the object tree to a file.

  2. Inspect32 - this tool dynamically displays the IAccessible properties when the cursor hovers over an MSAA-enabled window. In the screenshot below, the cursor is over the Firefox 3 address bar:

    screenshot

    Of these two tools, Inspect32 seems to have more stability problems, so I usually close it after I have what I need.

CXMSAALib Functions

Here are functions in CXMSAALib:

Function Description
CXMSAALib() Constructor
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

To integrate CXMSAALib into your own program, you first need to add following files to your project:

  • XMSAALib.cpp
  • XMSAALib.h

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.

MSAA Resources

CodeProject Articles Used/Referenced in this Article

Revision History

Version 1.0 - 2009 February 10

  • Initial public release

Usage

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Hans Dietrich
Software Developer (Senior) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.
 
Recently, I have moved to Los Angeles where I am doing consulting and development work.
 
For consulting and custom software development, please see www.hdsoft.org.






Comments and Discussions

 
GeneralMSAA tools PinmemberT800G14-Feb-14 8:43 
QuestionDoes not work with Chrome 29 Pinmembermicutzu1-Oct-13 4:06 
Generalsome problem in xp Pinmembercwangchao31-Mar-11 16:04 
AnswerRe: some problem in xp [modified] PinmentorHans Dietrich31-Mar-11 16:25 
QuestionHow to get it work under SYSTEM account?? PinmemberPetr Stejskal27-Aug-10 2:02 
AnswerRe: How to get it work under SYSTEM account?? PinmentorHans Dietrich22-Apr-11 22:53 
QuestionGet the event from a particluar application PinmemberRajmohan SK29-Apr-10 3:11 
GeneralNot enumerating into children PinmemberRensy Soft13-Sep-09 7:24 
GeneralRe: Not enumerating into children PinmemberRensy Soft13-Sep-09 9:34 
GeneralRe: Not enumerating into children PinmvpHans Dietrich13-Sep-09 9:41 
GeneralRe: Not enumerating into children PinmemberRensy Soft15-Sep-09 7:58 
GeneralRe: Not enumerating into children PinmvpHans Dietrich15-Sep-09 9:39 
GeneralRe: Not enumerating into children PinmemberRensy Soft15-Sep-09 10:12 
GeneralGreat Work But PinmemberInvincibleAngel21-Aug-09 23:34 
GeneralUnusably slow. PinmemberRensy Soft4-Jun-09 0:17 
GeneralRe: Unusably slow. PinmvpHans Dietrich4-Jun-09 0:22 
GeneralRe: Unusably slow - out-of-process-COM vs Tree-Size [modified] Pinmemberpg--az29-Jun-09 6:25 
GeneralRe: Unusably slow - out-of-process-COM vs Tree-Size PinmemberRensy Soft8-Sep-09 3:52 
GeneralRe: Unusably slow - out-of-process-COM vs Tree-Size [modified] Pinmemberpg--az9-Sep-09 21:52 
GeneralRe: Unusably slow - out-of-process-COM vs Tree-Size PinmemberRensy Soft13-Sep-09 6:33 
Generalgreat article Pinmemberqianwan703113-May-09 22:20 
AnswerRe: great article PinmentorHans Dietrich22-Apr-11 22:59 
GeneralAwesome!! PinmemberDr.Luiji10-Mar-09 2:15 
AnswerRe: Awesome!! PinmentorHans Dietrich22-Apr-11 22:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 10 Feb 2009
Article Copyright 2009 by Hans Dietrich
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid