How to Build Accessible Windows Forms Applications with .NET

icrosoft Active Accessibility is a technology that improves the way programs and the operating system can interact with accessibility aids. Active Accessibility has to be invisible to the user and be recognized only by special client software designed to help people with disabilities.

Active Accessibility is available for Win98, WinNT 4.0 SP6, Windows 2000, Windows XP, or newer operating systems. A version for Windows 9x is also available, although with some limitations.

What You Need
To get the most benefit from this article, you need a good understanding of C# and object-oriented programming and a general knowledge of the .NET environment, including Windows Forms and Custom Controls. Although a deep understanding of the system internals isn’t necessary, understanding its basics will be advantageous. The examples in this article should be used with the final release of Visual Studio.NET (2003) on Windows 2000 or XP machines. To be able to test the samples you will need to have accessibility clients installed. For more information check the documentation of your operating system.

Active Accessibility must provide several pieces of information about objects on the screen:

  • Name
  • Role (this describes the function of the object within the application)
  • Location
  • Current State
  • Parent
  • Child Count

If applicable the following properties must be supported as well:

  • Keyboard Shortcut
  • Default Action
  • Value
  • Child (if there are any accessible child objects)
  • Focus
  • Selection

The following properties are optional but should be supported to provide useful information about various visual elements, like bitmaps, charts, and others:

  • Description
  • Help Topic
  • Help

Active Accessibility also provides notifications of user interface changes via Windows Events and spatial and logical navigation for screen reader software. Spatial navigation is relevant only within the context of a single container, and therefore rarely meaningful to an end user. One rare case in which spatial navigation can be useful is within a data grid or a list view where elements are arranged in a navigable way?for example, where you can access data by moving left, right, up, or down within the view. Logical navigation is commonly used for hierarchically arranged objects with parents, children, and siblings?such as in a menu, tree view, or within control groups. Logical navigation uses terms such as parent, child, next, and previous for traversing object hierarchies. Because logical navigation is widely used by navigational aids, all programs supporting Active Accessibility must fully support this form of navigation.

What Are Accessibility Aids?
In general, accessibility aids are specialized programs and devices, such as the Braille bar (see the Related Resources links for more information) that help people with disabilities use computers more effectively. Aids fall roughly into the following categories:

  • Screen enlargers for people who have low vision
  • Screen readers for people who are blind
  • Voice input utilities for people who are not able to use mouse or keyboard for input
  • Alternative input devices
  • On-screen keyboards and keyboard enhancements for people that have problems using a keyboard, for example, the inability to hold down two or more keys at the same time)

Active Accessibility increases the options for people who depend on accessibility aids to use computers. Microsoft is not the only company developing aids; there are also many third party aids available. Visit the Microsoft Overview of Assistive Technology for a catalogue of certified aids.

How Does Active Accessibility Help Developers?
Active Accessibility provides dynamic link libraries that are incorporated into the operating system and offer standardized COM interfaces, API elements, and .NET Framework classes that cooperate with your applications and help replace the unreliable and less portable techniques used in the past, such as analyzing screenshots. Most system-provided user interface elements, such as list boxes, drop down lists, buttons, check boxes, and buttons are designed to expose this information by simply setting the accessibility properties. Notifications about events such as screen changes, enabling or disabling a control, and setting a default action are also fully supported by the Active Accessibility framework.

Active Accessibility Architecture
Applications that use only standard user interface elements typically get full Active Accessibility support without much additional development work on your part. However, some important exceptions to this rule are controls that:

  • Have been subclassed
  • Do not have the HASSTRINGS style set
  • Are owner-drawn

For these, you must provide custom accessibility code. Here’s a brief overview over the architecture of Active Accessibility, so that you can follow the sample source more easily.

About Servers and Clients
The dynamic link library OLEACC provides the Active Accessibility runtime and manages requests from clients for information about servers.

For this article, a client is any program that uses accessibility to access, identify, or manipulate the user interface. Thus the term client can include accessibility aids, automated testing tools, computer-based training applications?briefly, any application that consumes information exposed through active accessibility interfaces.

A server can be any control, module, or application that uses Active Accessibility to expose information about its user interface. Servers and clients communicate with one another by sending event notifications (for example by calling NotifyWinEvent) and responding to client requests for access to user interface elements (for example by handling WM_GETOBJECT messages). Clients register to receive notifications through a mechanism called Window Events, or WinEvents. Because the .NET Framework wraps WinEvents neatly, you don’t have to touch it when writing servers. You should take a look at WinEvents in the MSDN Library if you are interested in the details, but broadly, the rationale is that clients need to know when the server’s user interface changes so they can convey that information to the user.

Active Accessibility Objects
In accessible applications two types of UI elements provide accessibility information: accessible objects and simple elements. Although most applications contain both, accessible objects are more common than simple elements. To be an accessible object, a UI element must implement the IAccessible interface, whereas a simple element shares an IAccessible object with other elements and relies on that IAccessible object to expose its properties. A simple element requires not only an IAccessible object, but also a child ID; the IAccessible object shared among simple elements often corresponds to a common parent object in the user interface. For example, system dropdown lists expose an accessible object for the overall drop down list box and simple elements for each list item. In this case the IAccessible object for the drop down list is called the parent or container of the simple elements corresponding to the list items.

Build a Sample Application

?
Figure 1. Sample Accessibility App: The figure shows the sample application displaying a button, some values, and the custom bar chart control.

For this article I’ve prepared a small sample application with a standard Button control and a custom control representing a bar char (see Figure 1).

Accessibility Information for Existing Controls
It’s almost trival to implement Active Accessibility for existing framework-supplied controls. All you have to do is?supply values for the four properties AccessibleName, AccessibleDescription, AccessibleDefaultActionDescription, and AccessibleRole.

You can set three of these properties in the Properties window as shown in Figure 2; however, you can’t set the AccessibleDefaultActionDescription property via the properties window. Instead, you can set it with one line of code:

   this.button1.AccessibleDefaultActionDescription =       "some description about what will happen " +       "when you press this button";
?
Figure 2. Accessible Properties: The figure shows a portion of the properties window in Visual Studio containing Active Accessibility properties.

Accessibility Information for Custom Controls
If you require more accessible information to be included with your control (for example, simple elements for child controls) you can write your own class that derives from the AccessibleObject or Control.ControlAccessibleObject classes. You can find those in the Accessibility namespace. You must add a reference to the Accessibility assembly installed with the .NET Framework to get access to the AccessibleObject.

The source showing this is far too long for this article, but you can download the full source, so I’ll explain only the most important parts of the code here.

First you have to derive your class from Control.ControlAccessibleObject and write a constructor that supplies the base class with a reference to the parent of the AccessibleObject. The parent is always the control that you are extending with accessible information.

   public class AccSampleCtrlAccessibleObject :      Control.ControlAccessibleObject   {         private AccSampleCtrl ctrl;         public AccSampleCtrlAccessibleObject(         AccSampleCtrl owner) : base(owner)      {         ctrl = owner;      }      }   

To supply custom accessibility information you have to override the CreateAccessibilityInstance() method of your control and return your custom AccessibleObject instead of the default one:

   protected override AccessibleObject CreateAccessibilityInstance()   {      return new AccSampleCtrlAccessibleObject(this);   }

Next, you’ll need to override several properties and methods of the base class AccessibleObject as in the following code.

Author’s Note: It’s important to keep in mind that you also have to override the GetChildCount method if you are overriding the GetChild method!

   public override string Name   {      get      {         string name = ctrl.AccessibleName;         if(name!=null)         {            return name;         }         return ctrl.Text;      }      set      {         base.Name = value;      }   }      public override AccessibleRole Role   {      get      {         return AccessibleRole.Chart;      }   }      public override AccessibleStates State   {      get      {         return AccessibleStates.ReadOnly;      }   }      public override int GetChildCount()   {      return ctrl.Legends.Length;   }      public override AccessibleObject GetChild(int index)   {      if ( index >= 0 && index < ctrl.Legends.Length )         return ctrl.Legends[index].AccessibilityObject;      return null;   }

When overriding the methods from AccessibleObject don't forget that every Active Accessibility object must support navigation. The most common form of navigation is logical navigation, which is implemented within the method NavigateFromChild shown below. Note that this method is declared as internal?there's no need to call this method from outside the control's assembly.

   internal AccessibleObject NavigateFromChild(      AccSampleCtrlLegend.      AccSampleCtrlLegendAccessibleObject child,       AccessibleNavigation navdir)   {      switch(navdir)      {         case AccessibleNavigation.Down:         case AccessibleNavigation.Next:         {            return GetChild(child.ID+1);         }         case AccessibleNavigation.Up:         case AccessibleNavigation.Previous:         {            return GetChild(child.ID-1);         }         }      return null;   }

To implement spatial navigation you use the directional constants in the AccessibleNavigation enumeration?Up, Down, Left, and Right. Note that the method presented here is called from the overridden method navigate which could also be used directly to implement the navigation.

These were the tough parts of the custom control code. For the complete implementation of the accessibility sample control check out the accompanying download.

Testing Active Accessibility
The easiest way to test if your application supports accessibility aids correctly is to try to use them with your application. To start up the Active Accessibility Utility Manager press the Windows key on your keyboard and the letter U (?+ U). In the Utility Manager Application Window you can easily start and stop the different aids that are available with each default installation of Microsoft Windows XP. The most important aid to test with is Microsoft Narrator. You can also start it without the Utility Manger by typing "Narrator" at the command prompt or in the Run? window.

You can download additional tools from the Microsoft Web site that can help you when testing accessibility features. These include the following:

  • Accessibility Event Watcher (AccEvent)
  • Inspect Object (Inspect)
  • Accessible Explorer (AccExplorer)

At a minimum, test the user interface of each feature at its first and second levels. For example, in a dialog box containing tabs, test all buttons and tabs, and all subcontrols on the tabs, and any dialog boxes that appear when users click a button on the tab pages.

Active Accessibility is on the rise. Many companies are using it or are at least planning to support accessibility in the near future. Microsoft is promoting the benefits of Active Accessibility to the software industry, the accessibility community and others. It's good to see the increasing awareness about enabling people with disabilities to use computers. For many, the computer has become the primary source of information and work, enabling people to perform tasks that were formerly impossible. Ultimately, Microsoft Active Accessibility increases options for people who depend on accessibility aids to use computers.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: