Reintroducing MsaaVerify as an open source project on CodePlex

Prior to my retirement from accessibility (i’m still retired, btw), i wrote a testing tool for verifying the required MSAA properties needed for Assistive Technology devices, like screen readers, Braille displays, and so forth.  Working on the power toys for the past year has made me want to pick up the little guy again and try to finish all of the ideas i had started.  I’m a huge believer in leading by example, so i’ve been itching to start my own pet project on codeplex .  And of course, this little tool is a natural first choice. 

MsaaVerify Pet Project on CodePlex

Another motivation for reintroducing this tool stems from my overall community work.  I want to better understand community engagement.  It’s a part of a larger plan to understand the term community and everything that goes along with it.

Ways to Participate

Besides the obvious software development aspects of contributing code or bug reports, i could use some help with

  • What is the best way to represent pass / failure in the UI
  • How should I describe what changes need to be made to fix a failure

The more i work on this tool, the more i think that maybe a better home is in FXCop, but i want to get the proof of concept working first, then maybe port to FXCop.  Thoughts?

Current Release – MsaaVerify 1.1 Alpha

  • A rearchitectured baseline prototype with lots and lots of code clean-up
  • Verifies only push buttons and edit boxes
  • Verifies only one object at a time (and with the current design, if a child object is captures, e.g. a listview item, the parent object is the one that’s verified)
  • Updates to the UI from the version on GotDotNet

Future Releases – MsaaVerify 1.1 Beta

Once i have these things implemented, i’ll release a Beta version

  • Verification support for many more standard controls
  • Hopefully, updated UI for the verification results
  • Support for capturing a control based on tab order (needed to verify things like a text box’s name comes from the control that immediately precedes it in tab order)

And Further Out Future Releases

I’ve written a lightweight vision doc on the direction of the tool, some functionality i’d like to add to it, etc.

Another MSDN Blog that discusses accessibility – Microsoft Federal Developer Evangelism Team Blog

Back in September ‘05  (yeah, I’m just a little behind the times), the Microsoft Federal Developer Evangelism Team started blogging, including a category on Accessibility.  All of their content thus far is on ASP.NET.  So, if you need info on making accessibile ASP.NET applications (not my area of expertise), definitely check them out.

Federal Developer Weblog : Accessibility Category RSS

Role-Based Testing Strategy for Verifying Microsoft Active Accessibility

Below is something I’ve been working on for a while now, putting all of my thoughts regarding MSAA testing down onto paper.  Consider this the grand specification for MsaaVerify.  Provided i had enough time, this is everything i wanted to implement in MsaaVerify.  Hopefully someone out there will find this useful and can put it to use. 

Role-Based Testing Strategy for Verifying Microsoft Active Accessibility

This testing strategy assumes a UI control has correctly identified itself via a MSAA property called a role.  For example, an OK button on a dialog has a MSAA property called “Push Button”.  Based on the control’s role, a specific suite of tests for that particular control is run.  These tests verify that the control has implement its other properties and controls correctly, based on its supplied role.

For standard Windows controls, like a Push Button or an Edit Box, this verification is a straight-forward process. See http://msdn.microsoft.com/library/en-us/msaa/msaapndx_2a05.asp for examples.  But for more complex controls, where 2 controls merge, or new controls are created, the verification hasn’t been defined yet. 

Section 1 – Defining Test Cases

This first section is how to define the test cases.

  1. Run test suites against a UI control based on its MSAA role, defined by IAccessible::get_accRole.  The role is one of the standard Windows controls.  See http://msdn.microsoft.com/library/en-us/msaa/msaapndx_6ypa.asp for an example of how to implement MSAA for a push button.
  2. Combine test suites against a UI control, if the control’s MSAA role is a “hybrid”.  A hybrid control is where 2 standard Windows controls are combined to form one control.  For example, a Checked Tree View is a hybrid of a check box and a tree view.  To combine test suites, the more important verification for each property is used over the other.  For example, a check box does not implement IAccessible:;get_accValue; however, for a tree view item, IAccessible:;get_accValue returns the depth in the tree.  Hence for a Checked Tree View, the MSAA Value property test verifies that the correct depth in the tree is returned.
  3. Copy test suites against a UI control, if the control is a “clone” of some other standard Windows control.  A clone is a control that is completely new, but mimics the behavior of a standard Windows control.  For example, a developer might implement some snazzy new controls that resembles a floating balloon.  Whenever this control is clicked, a “tip of the day” appears.  Take away the eye candy, the control is really just a glorified push button.  Therefore, the first test suite must verify that the clone’s MSAA role is “Push Button”.  Then, the “Push Button” test suites are run.

Section 2 – Tweaking the Testing Intensity

Just like in any other aspect of software testing, there’s a dial that a software tester can turn up or turn down the amount or intensity of the applied testing.  The dial for testing MSAA can be viewed at the following 4 settings:

Dial Setting #1: Strictest level of testing

All expected method and properties for given role (as defined by the test suite) must be implemented and implemented correctly.  Anything else implemented is considered a failure.

Consider an OK button on a dialog. 

  1. The MSAA Default Action property for the button is “Press”.  If this method is not implemented correctly, ie “Click” is returned, or if this method isn’t implemented at all, a failure is reported
  2. The MSAA Value property for the button is “OK”.  A push button is not supposed to implement the Value property.  A failure is reported.
  3. The MSAA Name property for the button is not implemented.  All UI controls must have a name, so this property must be implemented.  A failure is reported.
  4. And so forth
Dial Setting #2: Moderately-Strict

Suppose a UI developer wants to specify more information than what was originally required for the control.  Consider a push button that performs an unusual action, but might not be intuitive from the push button’s caption or name.  The developer can use the MSAA Description property to describe the action, but it isn’t imperative to the user in operating the control.

Consider an OK button on a dialog. 

  1. The MSAA Default Action property for the button is “Press”.  If this method is not implemented correctly, ie “Click” is returned, or if this method isn’t implemented at all, a failure is reported
  2. The MSAA Value property for the button is “OK”.  A push button is not supposed to implement the Value property.  A failure is reported.
  3. The MSAA Name property for the button is not implemented.  All UI controls must have a name, so this property must be implemented.  A failure is reported.
  4. The MSAA Description property for the button is “Dismisses the dialog”.  A push button isn’t required to support the description property.  But, because the property is implemented, the test suites verify this is the expected description specified by the developer.
  5. And so forth
Dial Setting #3: Moderately-Relaxed

Ignores properties that were implemented, but were not expected to be implemented.   Note in the below example, part ‘b’ does not log a failure.

Consider an OK button on a dialog.

  1. The MSAA Default Action property for the button is “Press”.  If this method is not implemented correctly, ie “Click” is returned, or if this method isn’t implemented at all, a failure is reported.
  2. The MSAA Value property for the button is “OK”.  A push button is not supposed to implement the Value property; however, a failure is not reported, but a warning is logged instead.
  3. The MSAA Name property for the button is not implemented.  All UI controls must have a name, so this property must be implemented.  A failure is reported.
  4. And so forth
Dial Setting #4: Minimum Required level of testing

Perfect for regression tests, all UI controls must support these methods.  These are the highest priority tests that can be run for a control.  From http://msdn.microsoft.com/library/en-us/msaa/msaaccgd_95kk.asp, these properties and methods are Name, Role, State, Parent, Location, Navigate, and HitTest

Consider an OK button on a dialog.

  1. The MSAA Name property for the button is not implemented.  All UI controls must have a name, so this property must be implemented.  A failure is reported.
  2. And so forth

Flowchart describing Sections 1 and 2

 

Flowchart describing role base testing

Using the above approach in a testing tool or automation framework

 

Step 1:  Capture the MSAA object for a UI element by either method below
  1. AccessibleObjectFromWindow – the user specifies the window handle (HWND) for the control
  2. AccessibleObjectFromPoint – the (x, y) coordinates of any point within the control’s drawing boundary is specified.  Usually, a tool consists of a pair of crosshairs that the user clicks and drags over the desired control
Step 2:  Pass the generated MSAA object from step 1 into a MSAA Verifier class and the desired level of testing (see Section 2 above)
 
Step 3:  Obtain the MSAA role for the specified object by calling IAccessible::get_accRole from the MSAA object.
 
Step 4:  Apply the appropriate test suites for the desired level of testing.  Retrieve corresponding values from win32 API calls (test hooks, etc). 
  1. For example, a push button’s MSAA name comes from its caption.  Retrieve the UI Element’s caption and verify 1. the MSAA name is non-null and 2. it matches the caption from the control. 
  2. Another example, an edit box’s MSAA name comes from the control that immediate precedes it in tab order.  Verify the edit box’s name is the same as the label control’s caption found immediately to the left of the edit box (or above it, if a label isn’t found to the left).
Step 5:  Record test suite results and report.

What to do when TreeViews or ListViews don’t show selection or inactive selection

While working on a community app project (you’ll hear more on this later), I needed help setting the selection (and inactive selection) on a tree view. 

Just a refresher from my first ever blog post,

Explanation of Focus and Selection

Focus: Only one control or UI Element can take focus at a time. If I were to press a key on the keyboard, the keystroke can only be sent to that control with focus.

Selection: Multiple controls can have multiple items selected. List boxes can have as many or as few items selected.

Inactive Selection: When focus moves away from the list box (with selected items) to another control, those list box items are said to have inactive selection:

Active Selection: The selected list box item with focus. Hence, only one item can have Active Selection.

Suppose you have a form that consists of a button and tree view or list view with several nodes. Start with selecting one of the nodes either by clicking to tabbing/arrowing to it. When you tab away, the selection will disappear. The same will happen via code if you try to select a node. The node is actually selected, but there’s no visible indication.

To fix this, there’s a property called HideSelection.  After you drop your list view or tree view onto the form, set HideSelection = False. Now, you’ll see the selection or inactive selection whether you’re selecting via code or tabbing away from the control.

Same goes for Standard Win32 Controls. For example, on a standard Win32 tree view control, you’ll need to set the TVS_SHOWSELALWAYS style bit.

And I thought I had retired this category feed. Old habits die hard. <grins>

Moving on from Accessibility

On September 1st, I stepped down from my role on the Visual Studio Accessibility Team. This month marked my 3 year anniversary working on Accessibility. I feel that I have done everything that I could do in this space. And I saw such passion and dedication coming from members of my Accessibility Leadership Team that it just made sense to step-aside and let them take over.

To keep the Accessibility momentum going, we’ve created the Visual Studio Accessibility Blog. You’ll find all the most interesting articles and posts from my Accessibility category over on the VSAccessibility blog in an easy to read format.

I still meet with the leadership team every couple of weeks to help them with any questions, bugs, or issues that arise to ensure a smooth transition.

As for what is next for me, alongside owning the editor, I’m going to investigate white-box testing. Also, I want to be a test lead when I grow up, so I’m looking into taking management courses and assisting in such roles.

The Fundamentals of Accessibility

Consider this article your one-stop shop for all things IAccessible. Below is a summary of the most important topics under my accessibility category.

Getting Started

New to Accessibility? So was I three years ago. Get caught-up by reading my MSDN whitepaper on Testing for Accessibility. Also, remember that Accessibility isn’t a feature. Just like localization, globalization, security, performance, and so forth, it is a standard that must be addressed.

MSAA / IAccessible

If you want your feature to be accessible, you’ll need to implement IAccessible.

Must Read: Explanation of each of the IAccessible Properties

http://blogs.msdn.com/saraford/archive/2004/08/25/220499.aspx

Must Read: Which Control-Types Support Which Properties

http://blogs.msdn.com/saraford/archive/2004/08/20/217941.aspx

Must Read: How To Really Support MSAA Names

http://blogs.msdn.com/saraford/archive/2004/01/25/62669.aspx

Commonly Asked Questions regarding Invisible, Offscreen and Unavailable States

http://blogs.msdn.com/saraford/archive/2004/01/06/48091.aspx

Which Properties Must Be Localized

http://blogs.msdn.com/saraford/archive/2004/04/16/114809.aspx

Must Read: MSAA / IAccessible Samples

Fiona, one of the devs on my team VSCore, has put together a really nice sample on how to implement IAccessible for a Custom Push Button http://blogs.msdn.com/saraford/archive/2004/06/18/159730.aspx

Must Read: MSAA Testing Tools

Have you ever used AccExplorer or Inspect and wondered whether the information presented was correct? Have you ever wanted to know which controls really need Names, Keyboard Shortcuts, Descriptions, and so forth? It’s time to MsaaVerify! MsaaVerify will verify 9 Microsoft Active Accessibility properties for 10 Microsoft Active Accessibility Role types.

http://blogs.msdn.com/saraford/archive/2004/05/11/130002.aspx

Updated! How To Really Do Screen Reader Testing.

In the past, I’ve focused on testing MSAA Properties. Now we’re ready to take screen reading testing to the next level by adding Events into the algorithm. It is not only essential that a control support the correct MSAA properties, but it is also essential that the control fire the right event for these properties.

http://blogs.msdn.com/saraford/archive/2004/08/20/218078.aspx

Updated! Role-Based Testing Strategy for Verifying Microsoft Active Accessibility

This paper contains of my thoughts regarding MSAA testing.  Consider this the grand specification for MsaaVerify.  Provided i had enough time, this is everything i wanted to implement in MsaaVerify.  Hopefully someone out there will find this useful and can put it to use. 

http://blogs.msdn.com/saraford/archive/2005/06/06/425729.aspx

Accessibility Macros

As demo’ed at CSUN, these macros allow users to tweak the Visual Studio .NET 2003 IDE by easily increasing and decreasing font size, toggling colors in the editor to pure black on white (or vice versa), and maximizing tool windows.

http://blogs.msdn.com/saraford/archive/2004/05/14/132296.aspx

Bugs to look out for

A listing of unpopular bugs given to me by an Assistive Technology Vendor

http://blogs.msdn.com/saraford/archive/2004/01/06/48090.aspx

What the High Underline Letters Checkbox Actually Does

http://blogs.msdn.com/saraford/archive/2004/04/16/114935.aspx

http://blogs.msdn.com/saraford/archive/2004/04/27/121810.aspx

Why Radio Buttons don’t resize

http://blogs.msdn.com/saraford/archive/2004/05/25/141462.aspx

Channel 9 Video

My Channel 9 Interview on Accessibility and Visual Studio

http://channel9.msdn.com/ShowPost.aspx?PostID=5382

more at http://blogs.msdn.com/saraford/archive/2004/04/30/123993.aspx

CSUN

Presenting at CSUN

http://blogs.msdn.com/saraford/archive/2004/02/17/75295.aspx

Getting Ready

http://blogs.msdn.com/saraford/archive/2004/03/14/89611.aspx

References

http://blogs.msdn.com/saraford/archive/2004/03/17/91255.aspx

Blogging and Accessibility Presentation

http://blogs.msdn.com/saraford/archive/2004/06/14/155479.aspx

What do the MSAA Properties really mean?

Here’s a collective summary of what the different MSAA Properties really mean.

Reference: http://msdn.microsoft.com/library/en-us/msaa/msaaccgd_95kk.asp

IAccessible::get_accName

Every object must have a name. AccExplorer cannot show “NAMELESS” for this object. In addition, the AA name needs to be unique for every control on the dialog.

Exceptions:

Suppose you had a dialog with two buttons called “Browse.” As long as the tab order was correct, so you know which control was before each of the browse buttons, the names do not need to be unique; however, you would get extra points in the accessibility space if you did so.

IAccessible::get_accRole

Every object must have a role as defined in oleacc.h. The role defines which properties and methods make sense to implement and how to implement them for the control. If the role isn’t correct, the control will not be accessible to an assistive technology.

IAccessible::get_accState

Every object must have a state as defined in oleacc.h. The state describes what sort of state the control is in, whether it is available, invisible, selected, checked, and so forth. It is fundamentally important that the state correctly correspond to the actual window state of the control. For example, if a checkbox is checked, the “checked” state bit must be set.

If none of the state bits are set, the control is in a “normal” state. Actually, IAccessible::get_accState will return 0, so AccExplorer and Inspect will just show normal as the state text.

IAccessible::get_accParent

Every object has a parent. Most of the time, an object’s parent is its invisible window wrapper, needed for things like scrollbars, grip controls, and so forth. If the object is an item like a list box item, tree view item, its parent is the list box or tree view control.

IAccessible::get_accChildCount

Returns the number of children. If there are no children, return 0.

IAccessible::get_accDescription

This property is required for list boxes or list view controls where there are multiple columns. The description field is used to show the content in these secondary columns. 

The description property can also be used when you want to describe any picture or image on the control (say a button with the picture of a printer), but it can be used to supply additional information when it isn’t clear what the control does from the Name, Role, State, Value… etc, properties.  Usually, it depends on the AT whether this property is read. 

IAccessible::get_accDefaultAction

This property is a string from oleaccrc.dll that describes the default action that will occur when executing IAccessible::DoDefaultAction. For example, the default action of a push button is “Press”.

The default action may change depending on the state of the control. For example, if a checkbox is checked, the default action changes from “check” to “uncheck”.

IAccessible::get_accKeyboardShortcut

Returns the mnemonic, or the underlined letter, for a given control. See http://blogs.msdn.com/saraford/archive/2004/04/16/114779.aspx for more info.

IAccessible::get_accValue

Depends on the control whether to implement this property. Usually, if the control has additional info that cannot be conveyed via its name, like an edit box that has text or progress bar status, this information is used in the value. But, make sure you’re using a role that make sense to contain a value. If you put a value on a button, it might never be read by an AT because buttons usually don’t contain values.

IAccessible::get_accHelp

This property is when you want to give more information about what this control does. 

IAccessible::get_accHelpTopic

This is when you want to provide a URL for a given control.  Note: AccExplorer doesn’t show the HelpTopic correctly.  Inspect will show it correctly.

How To Really Do Screen Reader Testing (or Assistive Technology Testing)

In the past, I’ve focused on testing MSAA Properties. Now we’re ready to take screen reading testing to the next level by adding Events into the algorithm. It is not only essential that a control support the correct MSAA properties, but it is also essential that the control fire the right event for these properties.

Here is my new and approved Screen Reader Testing Model.

Perform initial sanity checking using either AccExplorer or Inspect to view the contents of the Accessible Object.

Step 1: Verify the control contain an AA object. A nameless window container is not a valid AA object for controls like List views, buttons, edit boxes, static text, and so forth.

Step 2: Verify the AA object has the correct role. For example, a list view is not a tree view, so it is not acceptable for a tree view control to be represented by a list view in the AA model.

Step 3: Verify tab order is correct. Point AccExplorer at the entire dialog. Then arrow down through the children. Make sure you have the yellow rectangle highlight selected, so that you can follow visually which objects are now in focus. The tab order must match the way the controls area laid out on the dialog, namely they should start in upper left corner and make their way down to the bottom right. AccExplorer lists the children of the dialog in tab order. To be more precise, the child IDs of the AA objects from the dialog are listed in tab order, so that’s how you can use that effect to test the dialog.

So much of MSAA is dependent on tab order. For example, an edit box gets its name from the label that immediately precedes it in tab order. So, if the tab order is incorrect, the edit box may not have an AA name, or even worse, have an AA name (or label) for another edit box.

Step 4: Verify focus never disappears. Focus must never ever disappear. Do all controls that require tab stops have tab stops? Ensure that no interaction is required via mouse alone.

Step 5: Verify all controls have AA names. All controls must have a name, except for a few exceptions, like a list view when it doesn’t have a label because of the design. Look at Windows Explorer. However, I don’t believe that this is necessarily correct. You can always put an invisible label in front of the list view to give it an AA name. The sighted user will never see the label (unless running Spy++ or AccExplorer), but the screen reader user will be able to read the list view’s AA name.

Perform deeper AA testing using either AccExplorer or Inspect to view the contents of the Accessible Object.

Step 6: Verify all controls have their correct MSAA Properties. Please see my post Which Controls Support Which MSAA Properties, and How These Controls Implement MSAA Properties.

Use AccEvent to verify the correct events are fired and your application does not crash with Assistive Technologies running

Step 7: Verify your application does not crash by running AccEvent while running user-scenarios on your application

First, you’ll need to enable all options for AccEvent.

  1. Launch AccEvent
  2. Select All Object Properties
  3. Select All Event Information
  4. Hit Apply / OK

Now with AccEvent running, interact with each control either through mouse or keyboard. You want to get the control to fire at least 1 event per event type. You’ll also want to perform as many user scenarios as possible. If the application crashes with AccEvent running, there exists a very high probability that the application will crash with an assistive technology (or screen reader) running. Also, if running accEvent causes a crash, it is very highly likely the application caused the crash.

If you have automated tests, try running all of your automated tests that interact with the UI while AccEvent is running minimized. Aren’t automated tests great! <grins>

Step 8: Verify that your MSAA implementation fires the correct event

The MSAA SDK has a listing of all possible Accessibility Events, along with detailed descriptions, located at http://msdn.microsoft.com/library/en-us/msaa/msaaccrf_7jlf.asp

Events that apply to all objects

EVENT_OBJECT_SHOW

A hidden object is shown. If an object contains children, only the parent object fires the event. For example, suppose a list view appears, that was previously invisible, with 5 list items. Only one event is fired.

An EVENT_OBJECT_SHOW event indicates that the STATE_SYSTEM_INVISIBLE bit is no longer set. It is overkill to fire an EVENT_STATE_CHANGE event for the invisible bit in this case.

EVENT_OBJECT_HIDE

An object is hidden. If an object contains children, only the parent object fires the event.

The EVENT_OBJECT_HIDE event indicates that the STATE_SYSTEM_INVISIBLE flag has been set. It is overkill to fire an EVENT_STATE_CHANGE event for the invisible bit in this case.

EVENT_OBJECT_REORDER

An object has added, removed, or reordered its children. For example, this event is generated by a list view object when the number of child elements or the order of the elements changes.

These events only apply to objects that support these states.

EVENT_OBJECT_FOCUS

An object has received the keyboard focus.

EVENT_OBJECT_SELECTION

The selection within an object that has children has changed.

EVENT_OBJECT_STATECHANGE

An object’s state has changed. For example, a state change occurs when a button object is pressed or released, or when an object is enabled or disabled.

EVENT_OBJECT_LOCATIONCHANGE

An object has changed location, shape, or size.

EVENT_OBJECT_VALUECHANGE

An object’s value property has changed.

Examples for testing using AccEvents

Example 1: How to Test for State Change Event (EVENT_STATE_CHANGE)

  1. Open Control Panel – Accessibility Options
  2. Check the “Use StickyKeys” checkbox
  3. Point AccExplorer at the Use StickyKeys checkbox
  4. Verify that the AA state shows “checked.” If this state isn’t set, the event fired will not contain the correct information.
  5. Uncheck “Use StickyKeys”
  6. Verify that the AA state shows normal
  7. Launch AccEvent with only OBJ_STATECHANGE selected from Events. This can be found under Options – Settings.
  8. Check the “Use StickyKeys” checkbox (either mouse or keyboard will work)
  9. Verify that checked appears for “Use StickyKeys” checkbox’s State Change event.

OBJ_STATECHANGE Name="Use StickyKeys" Role=check box State=focused,checked,focusable

If checked doesn’t appear, re-verify step 4. If OBJ_STATECHANGE isn’t fired, then it is a bug against the checkbox.

Example 2: How To Test for Focus Change Event (EVENT_FOCUS_CHANGE)

  1. Open Control Panel – Accessibility Options
  2. Verify that all controls that can receive user input receive focus via the keyboard
  3. Launch AccEvent with only OBJ_FOCUSCHANGE selected from Events. This can be found under Options – Settings.
  4. Tab to each control
  5. Verify that a focus changed event is fired for each object. For example, when tabbing from “Use StickyKeys” to “Settings”, the following info is recorded:

OBJ_FOCUS Name="Settings" Role=push button State=focused,focusable

Other Examples To Pay Attention To

Verify all tree view nodes fire state change events whenever you expand or collapse them.

Verify selection change events are fired when navigating among items in a list.

Verify a state change event is fired for all check boxes.

Verify if an action causes a new control to appear, the corresponding Show event is fired for that object.

Troubleshooting Screen Reading Issues where issues are against the application

Does the screen reader read only a few properties or does the screen reader read nothing at all?

If the screen reader reads only a few properties, which properties are not being read? Are they set in MSAA? If they are not set in MSAA, it is most likely a bug against the application. If they are set correctly in MSAA, are the correct AccEvents being fired? If no events are being fired, it is most likely a bug against the application.

If the screen reader doesn’t read at all, is an EVENT_FOCUS_CHANGE event fired? If yes, are the properties in the event meaningful in accordance with Which Controls Support Which MSAA Properties, and How These Controls Implement MSAA Properties? If the properties are not meaningful or no events are being fired, it is most likely a bug against the application.

View original comments

Which Controls Support Which MSAA Properties, and How These Controls Implement MSAA Properties

From time to time, I get questions of “Which properties do I need to support for my control?” or “What values do I specify for these properties.” I wrote the MsaaVerify Testing Tool to do this level of testing for you, but from a dev’s perspective, they need to know this information at design time, not at testing time. Consider this post to be a specification on how to implement (and test!) Windows controls for accessiblity.

Frequently Ask Questions regarding MSAA Properties

 

Which Properties Must Every Control Support?

There are 4 properties every control must support:

  • Name – absolutely all controls must have an MSAA name. Imagine a button not having a caption, or a checkbox without any text describing what you’re checking.
  • Role – describes what sort of control you’re interacting with. Imagine if a dev where to owner-draw all buttons to look like edit boxes. It would be very disconcerting to use such UI.
  • State- describes whether a checkbox is checked or not, whether the control is available, and so forth.
  • Parent – the object’s relationship to all other objects.

Can I Use E_NOTIMPL instead of DISP_E_MEMBERNOTFOUND?

No. Because of the time when MSAA was written, DISP_E_MEMBERNOTFOUND was used instead of E_NOTIMPL. Always return DISP_E_MEMBERNOTFOUND if a method or property is not supported.

What if another HRESULT is returned for a Property?

Then it is a bug. Only DISP_E_MEMBERNOTFOUND or S_OK are supported. For example, no properties that I am aware of should ever return S_FALSE.

Are Help and Help Topic really required?

No. Help and HelpTopic are not required. I have rarely seen them used by an Assistive Technology. HelpTopic is a URL that provides help for the given control and Help is just more info on how to use the control. To the best of my knowledge, HelpTopic is the same thing as if the user were to press F1 for a dialog in Visual Studio. The result is that a help topic link is opened for the user. Technically, you need to return DISP_E_MEMBERNOTFOUND for both of these; however, it isn’t necessarily a bug if the dev returns S_OK with a null string.

What Is a Normal State? Why isn’t there an Uncheck State?

MSAA States are represented as bits. If no bits are set, the control is said to be in a “normal” state. Actually ::get_accState will return 0. If a checkbox is checked, the “checked” state is set. If the checkbox isn’t checked, the “checked” state isn’t checked, hence the normal state.

What about Tables?

Check out this whitepaper about tables: http://msdn.microsoft.com/library/en-us/dnacc/html/ATG_MSAASupportforTables.asp

What if I have a control that merges a list view or tree view with check boxes?

Check out this whitepaper about list views / tree views with check boxes: http://msdn.microsoft.com/library/en-us/dnacc/html/ATG_UpdatedListViewWithCheckboxes.asp

What if I have a custom control (something I implemented myself) that doesn’t look anything like any standard Windows Controls? 

What you’ll want to do is to look at all of the MSAA properties for all of the standard Windows controls your custom control kinda looks like or kinda behaves like. Then you’ll need to merge these properties together.

Or say you’re designing something that doesn’t even look like a Windows control. You’ll want to match your control’s behavior as closely as possible to a Windows control. For example, say you implemented some color picker that contains a bunch of “boxes” that represent colors. The UI looks something like a color palette that you can navigate and select different colors, but what should the MSAA properties look like? One idea, and this is just an idea or suggestion (use at own risk), is to represent each of the boxes of the color palettes as a radio button in MSAA, because only one color can ever have selection. If the designer were to replace the color palette with a standard Windows control, he/she could use a radio button group. A color palette is just a better visual representation of the UI than the radio button group, but for MSAA, using a radio button group should work.

How To Implement MSAA for A Given Control

 

Button

Reference: http://msdn.microsoft.com/library/en-us/msaa/msaapndx_6ypa.asp

ChildCount – Return 0.  A button doesn’t have any children.

DefaultAction* – Required. Return “Press”.  Just use oleaccrc.dll to get the correct localization.

Description – 99% of the time, just return DISP_E_MEMBERNOTFOUND.  According to docs, this is used to describe an image on a button, but I’ve seen this used to describe what the button does (although help topic would be a better choice). 

KeyboardShortcut – Required. Returns the mnemonic.  All buttons must have a mnemonic. 

Name -  Required. Returns the caption.  If you have a button that has a graphic, you must use either Dynamic Annotation to set the AA name directly or use a win32 call to set an invisible caption on the button.

Parent – Required. Returns the invisible window container wrapper that has the same name of the control.  This window’s parent is the dialog itself.

Role – Required. ROLE_SYSTEM_PUSHBUTTON (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it
  • STATE_SYSTEM_PRESSED – if depressed
  • STATE_SYSTEM_DEFAULT – is default button on dialog

Value – Return DISP_E_MEMBERNOTFOUND

CheckBox

Reference: http://msdn.microsoft.com/library/en-us/msaa/msaapndx_4erc.asp

ChildCount – Return 0.  A checkbox doesn’t have any children.

DefaultAction -  Required. Depends on the current state of the checkbox.  If currently checked, return “Uncheck”.  If currently unchecked, return “Check”.  If currently a three-state checkbox, return “Toggle.”  Use oleaccrc.dll to get the correct localization.

Description – Return DISP_E_MEMBERNOTFOUND. 

KeyboardShortcut – Required. Returns the mnemonic.  All checkboxes must have a mnemonic. 

Name – Required. Returns the caption. 

Parent – Required. Returns the invisible window container wrapper that has the same name of the control.  This window’s parent is the dialog itself.

Role – Required. ROLE_SYSTEM_CHECKBUTTON (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it
  • STATE_SYSTEM_MIXED – indeterminate state
  • STATE_SYSTEM_CHECKED – checked

Value – Return DISP_E_MEMBERNOTFOUND

RadioButton

Reference: http://msdn.microsoft.com/library/en-us/msaa/msaapndx_7ulq.asp

ChildCount – Return 0.  A button doesn’t have any children.

DefaultAction – Required. Return “Check”  Use oleaccrc.dll to get the correct localization.

Description – Return DISP_E_MEMBERNOTFOUND. 

KeyboardShortcut – Required. Returns the mnemonic.  All radiobuttons must have a mnemonic. 

Name – Required. Returns the caption. 

Parent – Required. Returns the invisible window container wrapper that has the same name of the control.  This window’s parent is the dialog itself.

Role – Required. ROLE_SYSTEM_RADIOBUTTON (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it
  • STATE_SYSTEM_CHECKED – checked

Value – Return DISP_E_MEMBERNOTFOUND 

ComboBox

Reference: http://msdn.microsoft.com/library/en-us/msaa/msaapndx_53nc.asp.

For the Combo Box window:

ChildCount – Required. – Return ’3′.  (the push button, the edit box, and the drop-down list)

DefaultAction - Return DISP_E_MEMBERNOTFOUND

Description – Return DISP_E_MEMBERNOTFOUND 

KeyboardShortcut – Required. Returns the mnemonic from its label.

Name – Required. Returns its label.  Note: The label must precede (come before) the combo box in tab order.

Parent – Required. Returns the invisible window container wrapper that has the same name of the control.  This window’s parent is the dialog itself.

Role – Required. ROLE_SYSTEM_COMBOBOX (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it

Value – Required. Return the text within the edit box / combo box itself.

For the Combo Box button:

ChildCount – Return 0.

DefaultAction – Required. If the list isn’t opened, return “Open”; otherwise, “Close”.  Use oleaccrc.dll to get the correct localization.

Description – Return DISP_E_MEMBERNOTFOUND 

KeyboardShortcut – Required. Correct keyboard shortcut is “Alt+Down Arrow”.

Name – Required. If the list isn’t opened, return “Open”; otherwise, “Close”.  Use oleaccrc.dll to get the correct localization.

Parent – Required. Returns the combo box.

Role – Required. ROLE_SYSTEM_PUSHBUTTON (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_PRESSED – if depressed with list showing

Value – Return DISP_E_MEMBERNOTFOUND 

For the Combo Box Edit Box:

ChildCount – Return 0

DefaultAction – Return DISP_E_MEMBERNOTFOUND

Description – Return DISP_E_MEMBERNOTFOUND 

KeyboardShortcut – Required. Return DISP_E_MEMBERNOTFOUND 

Name – Required. Same as the combo box’s name

Parent – Required. Returns the combo box

Role – Required.  ROLE_SYSTEM_TEXT  (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it

Value – Required. The text within the edit box / combo box itself

For the Combo Box List:

ChildCount – Required. Return the number of items in the list

DefaultAction – Return DISP_E_MEMBERNOTFOUND

Description – Return DISP_E_MEMBERNOTFOUND 

KeyboardShortcut – Return DISP_E_MEMBERNOTFOUND 

Name – Required. Same as the combo box’s name

Parent – Required. Returns the combo box

Role – Required. ROLE_SYSTEM_LIST  (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it
  • STATE_SYSTEM_FLOATING – if it is opened

Value – Return DISP_E_MEMBERNOTFOUND 

For the Combo Box ListItem:

ChildCount – Return 0

DefaultAction – Required. Return “Double Click” Use oleaccrc for the correct localization

Description – Return DISP_E_MEMBERNOTFOUND 

KeyboardShortcut – Return DISP_E_MEMBERNOTFOUND 

Name – Required. The list item text

Parent – Required. Returns the list

Role – Required. ROLE_SYSTEM_LISTITEM  (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it
  • STATE_SYSTEM_SELECTABLE – if the user can select it
  • STATE_SYSTEM_SELECTED – if selected

Value – Return DISP_E_MEMBERNOTFOUND 

Edit Box

Reference: http://msdn.microsoft.com/library/en-us/msaa/msaapndx_7bu4.asp

ChildCount – Return 0.  An edit box doesn’t have any children

DefaultAction – Return DISP_E_MEMBERNOTFOUND

Description – Return DISP_E_MEMBERNOTFOUND. 

KeyboardShortcut – Required. Returns the mnemonic from the label.  All edit boxes must have a mnemonic. 

Name – Required. Returns the caption. Note:  The label must precede (come before) the combo box in tab order.

Parent – Required. Returns the invisible window container wrapper that has the same name of the control.  This window’s parent is the dialog itself.

Role – Required. ROLE_SYSTEM_TEXT (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it
  • STATE_SYSTEM_READONLY – Read-only edit box
  • STATE_SYSTEM_PROTECTED – password protected

Value – Required. The text within the edit box itself

List View

Reference: http://msdn.microsoft.com/library/en-us/msaa/msaapndx_3y5o.asp

ChildCount – Return the number of items in the list

DefaultAction – Return DISP_E_MEMBERNOTFOUND

Description – Return DISP_E_MEMBERNOTFOUND 

KeyboardShortcut – Required. About 90% of the time, there’s a label for the list view.  If there is a label, it must precede the list view in tab order.  And, it must have a mnemonic.

Name – Required. About 90% of the time, there’s a label for the list view.  If there is a label, it must precede the list view in tab order.

Parent – Required. Returns the invisible window container wrapper that has the same name of the control.  This window’s parent is the dialog itself.

Role – Required. ROLE_SYSTEM_LIST  (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it
  • STATE_SYSTEM_OFFSCREEN – the control is there, but just scrolled off the screen

Value – Return DISP_E_MEMBERNOTFOUND 

For the List View item

ChildCount – Return DISP_E_MEMBERNOTFOUND

DefaultAction – Required. Return “Double Click” use oleaccrc for correct localization.

Description – Required. If the list view contains columns, then each list view item is the text contained in the item’s second and subsequent columns. A comma is inserted between the text for each column.

KeyboardShortcut – Return DISP_E_MEMBERNOTFOUND

Name – Required. The same as the text of the list view item.

Parent – Required. Return the list view.

Role – Required. ROLE_SYSTEM_LISTITEM  (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it
  • STATE_SYSTEM_OFFSCREEN – the control is there, but just scrolled off the screen
  • STATE_SYSTEM_SELECTABLE – if the user can select it
  • STATE_SYSTEM_SELECTED – if selected
  • STATE_SYSTEM_MULTISELECTABLE – if multi-selected
  • STATE_SYSTEM_CHECKED – if it has checkboxes

Value – Return DISP_E_MEMBERNOTFOUND 

List Box

Reference: http://msdn.microsoft.com/library/en-us/msaa/msaapndx_1jy0.asp

ChildCount – Return the number of items in the list

DefaultAction – Return DISP_E_MEMBERNOTFOUND

Description – Return DISP_E_MEMBERNOTFOUND 

KeyboardShortcut – Required. Note: The label must precede the list view in tab order.  And, it must have a mnemonic.

Name – Required.  Note: The label must precede the list view in tab order.

Parent – Required: Returns the invisible window container wrapper that has the same name of the control.  This window’s parent is the dialog itself.

Role – Required. ROLE_SYSTEM_LIST  (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_FOCUSED – has focus
  • STATE_SYSTEM_FOCUSABLE – the user can tab to it
  • STATE_SYSTEM_OFFSCREEN – the control is there, but just scrolled off the screen
  • STATE_SYSTEM_UNAVAILABLE – if disabled

Value – Return DISP_E_MEMBERNOTFOUND 

List Box Item

For the list box item, see the “List View Item” above. 

Progress Bar

 Reference: http://msdn.microsoft.com/library/en-us/msaa/msaapndx_5u7g.asp

ChildCount – Return 0

DefaultAction – Return DISP_E_MEMBERNOTFOUND

Description – Return DISP_E_MEMBERNOTFOUND 

KeyboardShortcut – Return DISP_E_MEMBERNOTFOUND 

Name – Required. Note: If there is a label, it must precede the progress bar in tab order.  If it isn’t clear what this progress bar does, place an invisible label that precedes the progress bar in tab order, so that it will have an AA Name.

Parent – Required. Returns the invisible window container wrapper that has the same name of the control.  This window’s parent is the dialog itself.

Role – Required. Return ROLE_SYSTEM_PROGRESSBAR  (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled

Value – Required. Return a string from “0%” to “100%” that describes the progress.

Static Text

Reference: http://msdn.microsoft.com/library/en-us/msaa/msaapndx_4ws4.asp

ChildCount – Return 0

DefaultAction – Return DISP_E_MEMBERNOTFOUND

Description – Return DISP_E_MEMBERNOTFOUND 

KeyboardShortcut – Return DISP_E_MEMBERNOTFOUND (unless it is acting like a label)

Name – Required. The caption or the actual text of the static text.  Pretty simple.

Parent – Required. Returns the invisible window container wrapper that has the same name of the control.  This window’s parent is the dialog itself.

Role – Required. ROLE_SYSTEM_STATICTEXT  (defined in oleacc.h)

State – Required:

  • STATE_SYSTEM_INVISIBLE – if invisible (not shown yet)
  • STATE_SYSTEM_UNAVAILABLE – if disabled
  • STATE_SYSTEM_READONLY – if disabled

Value – Return DISP_E_MEMBERNOTFOUND

Back to blogging…

Wow, is it already the middle of August? Time really flies when you’re having fun or just working really hard. We’ve just completed our Accessibility and UI Consistency test passes, which I hope explains my absence from the blogsphere.

Here are some previews of upcoming blog posts:

  • I lost the admin’s cart – the missing chapter of Microserfs: Yep, I know you Microsofties are gasping as you’re reading this. “Who would have ever imagine that your success at Microsoft depends on whether you can return a 50 dollar Rubbermaid cart back to your floor,” quoth Aaron, my partner in crime.
  • How my screen reader testing methodology is wrong: I’ve recently learned that it is so much more important to test with AccEvent than it is to test with AccExplorer. AccExplorer is P2 (priority 2) whereas AccEvent is P1 (highest priority). I’ll share my algorithm on how to test with screen readers, which I now believe will provide everyone a rock-solid way to verify whether an issue is against your application or whether it is against the screen reader.
  • What I learned by failing Search and Rescue Training: Last November, I decided I was going to do Search and Rescue, having never camped out in the Pacific Northwest. Remember, I’m from New Orleans, so anything under 60 degrees is considered “freezing,” and yet, there I was trying to sleep in one of those mummy-like sleeping bags in 23 degree weather. Who would have thought hiking boots could actually freeze without water? <grins>
  • Lance Armstrong is my hero: He has been my hero since 1996 where he won his first Tour de France stage. I was an exchange student in France at the time, and I had this magazine in French that showed Lance winning that first stage. It is probably still hanging up on the wall in my bedroom at my parents’ house. BTW, what is up with those OLN announcers? Is that what happens when you’re only a sports announcer once a year?
  • Bad karate fighter, no cookie: I got so busy with work that I didn’t test last week for my second brown belt. But then again I reminded myself that the reason I was doing karate was to get back into shape and to relieve stress, and not to get stressed out over getting my black belt. I’ve been invited to participate in a karate competition down in Las Vegas, so I will start training, and blogging, about that.
  • SaraF is heading back to the N’awlins homeland for the first time in 3+ years: My grandmother had 12 kids on my mom’s side, and the youngest is turning 50 this year. They are having a family reunion for her birthday. One thing to note about my family is that they are a little different. In high school, I once wrote a short story about Thanksgiving at my house, and it won 3rd place in the state of Mississippi among high school students in the FICTION category. I think Mississippi didn’t want to admit that we come from there.