An Introduction to Windows App Accessibility — Preparing for UI Automation and Reasonable-Accommodation Requirements

· · Accessibility, UI Automation, Windows, WinForms, WPF, Reasonable Accommodation, Screen Readers, Disability Discrimination Act, Business Applications

“A mid-career hire who is visually impaired cannot use the core order-entry app with a screen reader. They use a web browser and mail without trouble, but only our business app’s reading does not work properly. Can something be done?” — Consultations of this kind from customers’ IT departments have been increasing.

One background is the legal framework. The 2021 amendment to the Act for Eliminating Discrimination against Persons with Disabilities took effect on 1 April 2024, and the “provision of reasonable accommodation” to persons with disabilities became an obligation for businesses as well.1 Further, an employee–company relationship such as the opening one (the employment field) is the domain of the Act on Employment Promotion of Persons with Disabilities, which has obligated employers to provide reasonable accommodation since April 2016.2 The idea that “accessibility is a website topic and has nothing to do with in-house Windows apps” no longer holds, either legally or in practice.

On the other hand, from the development floor, “we do not know what to do” is an honest place to be. Accessibility for Windows desktop apps has less information than the Web, and there is no magic after-the-fact solution. There is no need to be pessimistic, either. If you understand the mechanism by which a screen reader reads an app (UI Automation) and take on board the basics of name, keyboard, and colour, the usability of a business app improves substantially. And much of that is an improvement that raises every user’s productivity, with or without a disability.

Aimed at developers of Japanese business apps and at IT staff, this article connects in one pass from a minimum sorting-out of the legal framework and the standards, through the mechanism of UI Automation, implementation in WinForms/WPF, keyboard operation, colour and contrast, and verification tools, to a realistic way of setting priorities.

The flow of this articleThe structure of this article, connecting in order from sorting out the legal framework and the standards through the mechanism of UI Automation, implementation in WinForms and WPF, keyboard operation, colour and contrast, verification tools, and how to set prioritiesSorting out the legal framework and the standardsThe mechanism of UI AutomationImplementation in WinForms/WPFKeyboard operationColour and contrastVerification toolsHow to set priorities

Figure 1: This article connects the legal framework through mechanism, implementation, verification, and priorities in a single flow.

1. The Bottom Line First

  • The provision of reasonable accommodation has been an obligation for businesses as well since 1 April 2024. When a person with a disability indicates the intent to have a barrier removed, a response within a range that is not an excessive burden is required. The employment field is under the Act on Employment Promotion of Persons with Disabilities, and that has been an employer obligation since April 2016.12
  • Reasonable accommodation is a process of “responding to an individual request through constructive dialogue”; making the app easier to use in advance is “environmental improvement” (an effort obligation). Perfect advance support is not the obligation; what matters is not unilaterally refusing dialogue.1
  • The technical criteria for accessibility are concentrated in WCAG (JIS X 8341-3:2016). JIS X 8341-3:2016 is a corresponding standard with the same content as WCAG 2.0, and W3C’s WCAG2ICT gives guidance on applying it to non-Web software. A desktop app can be inspected with the same thinking.34
  • A screen reader reads an app through UI Automation (UIA). The properties each element on the UIA tree holds — Name, ControlType, and the like — and the control patterns such as Invoke, Value, and SelectionItem are the material for announcement and operation.5
  • A button whose Name is empty is announced only as “button”. The highest-priority fix is naming. WinForms uses AccessibleName and associating a Label with tab order; WPF uses AutomationProperties.Name/LabeledBy.67
  • Being able to reach every function from the keyboard alone is a WCAG success criterion (2.1.1) and, at the same time, a skilled operator’s input speed itself. Putting tab order, access keys, and focus indication in place connects directly to efficiency for every user.8
  • Take a text contrast ratio of 4.5:1 or more as a guide, and do not convey information by colour alone. In a contrast theme (high contrast), respect system colours rather than hard-coded colours.89
  • Combine verification with FastPass in Accessibility Insights for Windows and a hands-on check with a screen reader. Because they sit on the same UIA foundation, this work also pays off mutually with UI automated-testing assets such as FlaUI.10
  • You do not need to fix every screen at once. The realistic order is (1) from the screens that user uses, (2) new development is standard-compliant, (3) roll out sideways by fixing shared controls.

In one sentence: accessibility support is “exposing the correct name and operations on the UIA tree, and keeping the basics of keyboard and colour”.

2.1. The Act for Eliminating Discrimination against Persons with Disabilities — From April 2024, Businesses Too Are Obligated to Provide Reasonable Accommodation

The Act for Eliminating Discrimination against Persons with Disabilities is a law that prohibits “unjust discriminatory treatment” of persons with disabilities by administrative organs and businesses, and requires the “provision of reasonable accommodation”. In the 2021 (Reiwa 3) amendment, the provision of reasonable accommodation by businesses, which had been an effort obligation, became an obligation, and the amended Act took effect on 1 April 2024 (Reiwa 6).1

According to the Cabinet Office leaflet, the provision of reasonable accommodation is responding, within a range that is not an excessive burden, when a person with a disability indicates the intent that some response is needed to remove a barrier in society. And because the content differs by disability characteristic, scene, and situation, a “constructive dialogue” in which the person with a disability and the business stack dialogue and consider a response together is emphasised. Unilaterally refusing constructive dialogue is stated as potentially constituting a violation of the obligation to provide reasonable accommodation.1

Two practical distinctions matter here.

  1. “Having everything in place in advance” is not what became an obligation. Advance improvement measures aimed at an unspecified number of persons with disabilities — the soft side such as reviewing a manual and training, the hard side such as making a facility barrier-free — are called “environmental improvement”, and this is an effort obligation.1 Putting a business app in a state usable with a screen reader in advance can be thought of as an environmental-improvement effort. The further environmental improvement has gone, the lighter the burden of providing individual reasonable accommodation.
  2. The employment field is not under the Act for Eliminating Discrimination against Persons with Disabilities but under the Act on Employment Promotion of Persons with Disabilities. The same leaflet also states that employment and work follow the provisions of the Act on Employment Promotion of Persons with Disabilities.1 And under that Act, by the amendment that took effect in April 2016 (Heisei 28), the prohibition of disability discrimination in employment and the provision of reasonable accommodation within a range that is not an excessive burden have been obligated of employers.2 The opening consultation of “an employee cannot use the business app” has, in fact, been in the domain of obligation long before 2024.
The positioning of reasonable accommodation and environmental improvementThe relationship between a general business and a person with a disability is under the Act for Eliminating Discrimination against Persons with Disabilities, and providing reasonable accommodation by responding to an individual request through constructive dialogue has been an obligation since April 2024; the employment field has been an employer obligation since April 2016 under the Act on Employment Promotion of Persons with Disabilities; making the app easier to use in advance is environmental improvement, an effort obligationBusiness + disabilityEmployment / workWhich scene?Discrimination ActEmployment ActRequest via dialogueProvide accommodationObligation since 2024Provide accommodationObligation since 2016Easier app in advanceEnv improvementeffort obligation

Figure 2: The governing Act splits by scene; reasonable accommodation is an obligation, and advance fixes are environmental improvement, an effort obligation.

How an individual case is treated in law depends on the situation. This article does not step into legal interpretation; it proceeds from the viewpoint of what an engineer can do when a response is requested. For primary sources, refer to the Cabinet Office and Ministry of Health, Labour and Welfare materials.12

2.2. JIS X 8341-3 and WCAG — The “Web Criteria” Extend to Software Too

On the technical-criteria side, they are concentrated in JIS X 8341-3:2016. This standard is a corresponding standard of ISO/IEC 40500:2012, and the body of the standard is the same content as W3C’s WCAG 2.0.3 If you want to know concretely what “accessibility support” consists of, reading WCAG success criteria (now extended in WCAG 2.1/2.2) is the shortest path, and a Japanese translation by WAIC is also published.8

The question “is WCAG a criterion for Web content?” is fair, but W3C has organised, in a Group Note called WCAG2ICT (Guidance on Applying WCAG 2 to Non-Web Information and Communications Technologies), how to apply WCAG 2.0/2.1/2.2 success criteria to non-Web documents and software.4 In other words, thinking such as “text alternatives”, “contrast”, “keyboard operation”, and “colour is not the only means” can be applied to a Windows desktop app in the same framework as the Web. Chapters 3 onward of this article drop that thinking into concrete WinForms/WPF implementation.

The relationship between JIS X 8341-3 and WCAGJIS X 8341-3:2016 is a corresponding standard with the same content as WCAG 2.0, and WCAG2ICT shows how to apply WCAG success criteria to non-Web software, so a Windows desktop app can be inspected in the same frameworkA corresponding standard with the same contentWCAG 2.0 (W3C)JIS X 8341-3:2016WCAG2ICTApply to non-Web softwareA Windows desktop app

Figure 3: JIS X 8341-3:2016 is a corresponding standard of WCAG 2.0, and WCAG2ICT extends the same criteria to desktop apps.

3. How Assistive Technology Reads an App — The UI Automation Trio

3.1. The UIA Tree, Properties, and Control Patterns

Windows has an accessibility foundation called UI Automation (UIA) built in. UIA is a mechanism that lets assistive technology such as a screen reader obtain UI information and operate the UI by means other than standard input, and it mediates between the app side (the provider) and the assistive-technology side (the client).5

The world of UIA can be understood as the following trio.5

Element Role Representative examples
UIA tree A tree that starts from the desktop as the root and continues window → control. Assistive technology walks this tree to grasp the UI Window, pane, button, edit box
Properties Values that represent the nature of each element Name (purpose), ControlType (kind), AutomationId (identifier), IsEnabled, IsKeyboardFocusable
Control patterns A vocabulary of “operations you can do” per kind Invoke (press), Value (read/write a value), SelectionItem (select), Toggle (on/off), ExpandCollapse (expand/collapse)

When a screen reader focuses a button, the announcement “Confirm order button” is, roughly, the combination of Name + control type. When the user performs an “execute” operation, assistive technology presses that button through the Invoke pattern. In other words, if Name and the patterns are exposed correctly it can be read and operated; if they are not exposed, it is the same as not existing even if it is visible on screen.

The UI Automation trioThe app, as a provider, exposes each element's properties and control patterns on the UIA tree; the screen reader, as a client, announces Name and ControlType and operates through patterns such as InvokeAnnouncesOperatesApp (provider)UIA treeProperties (Name, ControlType, and the like)Patterns (Invoke, Value, and the like)Screen reader (client)

Figure 4: The screen reader uses the properties and patterns the app exposed on the UIA tree for announcement and operation.

3.2. A Screen Reader Is a UIA Client

The main screen readers used on Windows include Narrator, built into Windows; NVDA,11 which is free and open source; and PC-Talker, a commercial product widely used in Japan. The style of announcement differs among them, but the primary path for reading a desktop app’s UI is UIA in every case. That is why the app-side response is not “support for a particular screen reader” but concentrates on exposing the correct information to UIA.

The common path of the main screen readersIf the app exposes the correct information to UIA, Narrator, NVDA, and PC-Talker can all read the UI by the same path, so the app-side response is not aimed at a particular screen reader but concentrates on exposing to UIAExposes informationAppUI Automation (UIA)NarratorNVDAPC-TalkerThe response concentrates on exposing to UIA

Figure 5: The main screen readers all take UIA as the path, so the app’s response concentrates on exposing to UIA.

3.3. What Is a “Button Whose Name Is Empty” Announced As?

One concrete example. Suppose a toolbar has a Save button that displays only a floppy-disk icon. To a sighted user the icon conveys the meaning, but if Name is left empty, a screen reader announces this button only as “button”. If the neighbouring “Open” and “Print” are the same, the user hears only “button, button, button” and has no means of knowing which is which. Microsoft’s accessibility-fix guide also lists a button with no Name, and an image announced only as “Image”, as representative problems that stop the user’s work.7

Fortunately, both WinForms and WPF standard controls have UIA support from the start, and in many cases Name is decided automatically from text or a label. What breaks is usually one of (1) icon-only, with no material for a name, (2) no association with a label, or (3) custom drawing that does not put information on the UIA tree. The next two chapters look at how to fix it per framework.

Three typical ways announcement breaksAnnouncement breaks when there is no material for a name because it is icon-only, when there is no association with a label, or when custom drawing does not put information on the UIA tree, and it ends up being announced only as buttonIcon-only, no materialName becomes emptyNo association with a labelCustom drawing puts out no informationAnnounced only as button

Figure 6: Announcement breaking usually comes down to one of three patterns: insufficient material for a name, insufficient association, or custom drawing.

4. Implementation in WinForms — AccessibleName and Tab Order

4.1. Controls Whose Text Becomes Name Automatically, and Controls Whose Text Does Not

In WinForms, a control that displays text, such as a Button or a CheckBox, uses the value of the Text property as the UIA Name. On the other hand, ComboBox, ListBox, ListView, PictureBox, ProgressBar, TabControl, TextBox, TreeView and the like do not make Text the Name. These need a name by another means.6

The most maintainable way is to place a descriptive Label in the immediately preceding tab order of the target control. If you set the target control’s TabIndex to come immediately after the Label’s TabIndex, that Label’s text is used automatically as the UIA Name. The label visible on screen and the announcement match, and you do not have to manage the wording twice.612

If you cannot place a Label, set AccessibleName explicitly. You can also set AccessibleDescription if a supplementary explanation is needed, and AccessibleRole if the role differs from the appearance.13

How a WinForms control's name is decidedFor Button and the like, Text becomes the UIA Name as-is; for controls such as TextBox whose Text is not reused, the text of a Label placed in the immediately preceding tab order is used; if you cannot place a Label, set AccessibleName explicitlyYesNoYesNoControlA kind whose Text becomes Name?Text becomes Name as-isA Label in the immediately preceding tab order?The Label's text is used as NameSet AccessibleName explicitly

Figure 7: For a WinForms Name, choose how to decide it in the order Text, a Label in the immediately preceding tab order, AccessibleName.

// An icon-only toolbar button: state the name for announcement explicitly
saveToolStripButton.AccessibleName = "Save";

// An image-only button: name + a supplementary explanation
btnSearchCustomer.AccessibleName = "Search customer";
btnSearchCustomer.AccessibleDescription = "Search the customer master by customer code or name";

// Set it directly on an input field where you cannot place a Label in the immediately preceding tab order
txtOrderNo.AccessibleName = "Order number";

// A PictureBox reused as a chart display: match the role to the reality as well
pictureBoxChart.AccessibleRole = AccessibleRole.Chart;
pictureBoxChart.AccessibleName = "Monthly order-count chart";

As a caveat, if you set AccessibleName once in Visual Studio’s Properties pane and then clear it, an empty-string setting can remain in the designer file and interfere with the default name resolution. Delete the corresponding line from the designer file.6

The problem of an empty-string AccessibleName remainingIf you set AccessibleName once in the Properties pane and then clear it, an empty-string setting remains in the designer file and interferes with the default name resolution, so you fix it by deleting the corresponding line from the designer fileSet AccessibleNameClear it in the Properties paneAn empty-string setting remainsIt interferes with the default name resolutionDelete the corresponding line from the designer file

Figure 8: Clearing it in the Properties pane still leaves an empty string, so you fix it by deleting the corresponding line from the designer file.

4.2. Common Improvements on an Order-Entry Screen

The places we actually often fix in business apps are summarised as a checklist.

Common state Problem How to fix it
An icon-only ToolStripButton Announced only as “button” Set AccessibleName
There is a Label near the TextBox but the tab order is scattered The input field’s name is empty, or becomes an unrelated name Place the input field immediately after the Label’s TabIndex
A PictureBox used as a button via Click The role is not conveyed as a button, and it cannot be pressed from the keyboard Replace it with a Button, or set AccessibleRole/AccessibleName plus keyboard support
A DataGridView column header is empty or symbols only The meaning of the column is unclear when a cell is announced Set a meaningful column name on HeaderText
Only a Panel is used to group contents, and the heading is an image You cannot tell which input group it is Use a GroupBox, or make the heading a Label

Each is a fix of a few lines, but for a screen-reader user it is the fork between “a screen you cannot use” and “a screen you can use”.

5. Implementation in WPF — AutomationProperties and AutomationPeer

5.1. AutomationProperties.Name / LabeledBy / HelpText

In WPF, a control whose Content is a string, such as a Button, uses that content as the UIA Name. An icon-only button (Image or Path) has no material for a Name, so you state it with AutomationProperties.Name, or if there is nearby display text you associate it with AutomationProperties.LabeledBy.7

TextBox has an important caveat. A TextBlock’s Text is reused as Name, but a TextBox’s Text is exposed on the UIA Value property side and does not become Name. For an input field, associating the display-label TextBlock with LabeledBy is the first candidate. Announcement and on-screen display match, and you also avoid managing the wording twice.14

<!-- An input field: associate the display label with LabeledBy -->
<TextBlock x:Name="OrderNoLabel" Text="Order number" />
<TextBox
    AutomationProperties.LabeledBy="{Binding ElementName=OrderNoLabel}"
    AutomationProperties.AutomationId="OrderNoTextBox" />

<!-- An icon-only button: state the name, and a supplement if needed -->
<Button
    AutomationProperties.Name="Confirm order"
    AutomationProperties.HelpText="Confirm the order being entered and allocate inventory">
    <Path Data="{StaticResource CheckIconGeometry}" Width="16" Height="16" />
</Button>
How a WPF control's name is decidedA control whose Content is a string uses that content as Name; otherwise associating a nearby display label with LabeledBy is the first candidate; if that is also absent, state AutomationProperties.Name; a TextBox's Text is exposed on the Value side, not as NameYesNoYesNoControlIs Content a string?The content becomes NameA nearby display label?Associate with LabeledBySet Name explicitlyA TextBox's TextExposed as Value, not Name

Figure 9: For a WPF Name, decide in the order Content string, LabeledBy, an explicit setting; a TextBox’s Text does not become Name.

Supplementary information that does not fit in Name can be exposed with AutomationProperties.HelpText.7 Also, AutomationId is an identifier used for element identification in UI automated testing, so deciding a naming convention at screen-design time pays off later (covered in depth in “UI Automated Testing for Windows Desktop Apps”).

5.2. A Custom Control Needs an AutomationPeer

A custom control that you draw yourself cannot, as-is, expose meaningful information on the UIA tree. In WPF you override OnCreateAutomationPeer on a UIElement-derived class and return an AutomationPeer-derived class to expose name, kind, and patterns. If you are inheriting an existing control, inheriting the corresponding Peer (ButtonBaseAutomationPeer for ButtonBase) lets you take over already-implemented behaviour.15

How information is exposed via AutomationPeerA custom control exposes name, kind, and patterns by overriding OnCreateAutomationPeer and returning an AutomationPeer-derived class; if you are inheriting an existing control, inherit the corresponding Peer and take over already-implemented behaviourCustom controlOnCreateAutomationPeerReturn a Peer-derived classExpose name, kind, and patternsInherit an existing controlInherit the corresponding PeerTake over already-implemented behaviour

Figure 10: A custom control returns a Peer from OnCreateAutomationPeer and exposes information to UIA.

// An example of a control that custom-draws line status as a coloured lamp
public class StatusLamp : Control
{
    public static readonly DependencyProperty IsOnlineProperty =
        DependencyProperty.Register(nameof(IsOnline), typeof(bool), typeof(StatusLamp),
            new FrameworkPropertyMetadata(false,
                FrameworkPropertyMetadataOptions.AffectsRender, OnIsOnlineChanged));

    public bool IsOnline
    {
        get => (bool)GetValue(IsOnlineProperty);
        set => SetValue(IsOnlineProperty, value);
    }

    internal static string NameFor(bool isOnline)
        => isOnline ? "Line status: online" : "Line status: offline";

    private static void OnIsOnlineChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // Raise a UIA property-changed event the moment the value changes. Without this,
        // a screen reader keeps the old name and cannot notice the change of state
        if (UIElementAutomationPeer.FromElement((UIElement)d) is AutomationPeer peer)
        {
            peer.RaisePropertyChangedEvent(
                AutomationElementIdentifiers.NameProperty,
                NameFor((bool)e.OldValue), NameFor((bool)e.NewValue));
        }
    }

    protected override AutomationPeer OnCreateAutomationPeer()
        => new StatusLampAutomationPeer(this);
}

public class StatusLampAutomationPeer : FrameworkElementAutomationPeer
{
    public StatusLampAutomationPeer(StatusLamp owner) : base(owner) { }

    protected override AutomationControlType GetAutomationControlTypeCore()
        => AutomationControlType.Text; // Text-equivalent if it is a status display with no operation

    protected override string GetNameCore()
        => StatusLamp.NameFor(((StatusLamp)Owner).IsOnline);
}

Returning a name is not enough; telling it with an event the moment it changes is also the Peer’s job. Assistive technology does not have its own timing for re-fetching a value, so an implementation that does not raise a change event is in a state of “correct only when asked again”, and a screen-reader user is not told of the change of state.

The flow of telling a screen reader of a change of stateThe moment the control's value changes, the AutomationPeer raises a Name property-changed event; assistive technology does not re-fetch on its own, so without the event it stays on the old name and cannot notice the changeScreen readerAutomationPeerControlScreen readerAutomationPeerControlWithout the event it stays on the old nameThe IsOnline value changesRaise a Name property-changed eventAnnounce the new state

Figure 11: A change of value reaches a screen reader only when the AutomationPeer tells it with a change event.

If the custom control has an operation (it can be pressed, its value can be changed, it can be selected), you override GetPattern and provide a pattern interface such as IInvokeProvider or IRangeValueProvider.15 The point is that if you build the Peer as well on the shared-control-library side, every screen that uses it becomes supported automatically. That is the foundation of Chapter 9’s “roll out sideways”.

6. Can You Reach Every Function from the Keyboard Alone?

WCAG success criterion 2.1.1 (Keyboard) requires that all functionality of the content is operable through a keyboard interface.8 A screen-reader user in principle does not use a mouse, so a function you cannot reach from the keyboard is the same as a function that does not exist. The inspection viewpoints are as follows.

Viewpoint What to confirm Main means in WinForms / WPF
Tab order Does the Tab-key movement order match the visual order (top-left → bottom-right)? Tidying TabIndex, setting TabStop
Access key Can you move directly to a main item with Alt+a letter? In WinForms, & in Text; in WPF, _ in the header
Shortcut Is there a standalone key for frequent operations (save, search, confirm)? Assigning Ctrl+S and the like, showing it on the menu
Focus indication Can you follow with your eyes where focus is now? Do not remove the focus rectangle; draw it yourself when you custom-draw
Mouse-only functions Is there a function usable only by double-click, right-click, drag, or hover? Offer the same function from a menu or a key as well
Dialog Do Enter = the default button and Esc = cancel work? AcceptButton/CancelButton, IsDefault/IsCancel

The WinForms accessibility walkthrough also lists, as basics, placing a label in the immediately preceding tab order of an input field, and putting access keys on the controls and menus the user wants to move to.12

What we want to emphasise is that this is not “an extra cost for disability support”. In a routine job such as order entry, whether you can complete input without taking your hands off the home position is what decides an operator’s throughput as-is. A disordered tab order or a mouse-required operation is a defect that shaves a little off every user’s productivity every day. Accessibility support and keyboard efficiency are just two names for the same work (for priorities by usage environment, see also “Windows App UX Design”).

The dual effect of putting the keyboard in orderPutting tab order, access keys, and focus indication in place produces two effects at once — an assistive-technology user can reach a function, and every operator's input speed — and a function usable only with the mouse is the same as a function that does not existPut keyboard in orderAssistive-tech usersEvery operator's speedA mouse-only functionSame as nonexistent

Figure 12: Putting keyboard operation in order realises assistive-technology support and efficiency for every user at the same time; a mouse-only function is the same as not existing.

7. Colour and Contrast — 4.5:1 and “Colour Is Not the Only Means”

7.1. The Guide for Contrast Ratio Is 4.5:1

WCAG success criterion 1.4.3 (Contrast (Minimum)) requires a contrast ratio of at least 4.5:1 for text and images of text, and at least 3:1 for large text.8 A modern design that places light-grey text on a white background is not rare in falling short of this criterion. Users of a business app include people whose vision and colour vision have changed with age, and people who use it in a poorly lit environment such as a factory. Get into the habit of measuring with a contrast checker at design review.

7.2. Do Not Convey Information by Colour Alone

Success criterion 1.4.1 (Use of Color) is that colour must not be the only visual means of conveying information.8 Typical examples in a business app are as follows.

  • Showing an error row in red text only → also provide an error icon and a message column
  • Showing a required field by the label colour only → add a “*” or the wording “Required”
  • Showing status by the lamp colour only → make it colour + shape, or wording (“Running”, “Stopped”)

Given the diversity of colour vision, this too is not a “special response” but a basic of display design.

Replacing information conveyed by colour aloneA display that shows an error in red text only is replaced with an error icon plus a message column; a display that shows a required field by the label colour only is replaced with adding the wording Required; a display that shows status by the lamp colour only is replaced with combining shape or wordingAn error in red text onlyAlso provide an icon and wordingRequired by the label colour onlyAdd the wording RequiredStatus by the lamp colour onlyCombine colour with shape or wording

Figure 13: Typical examples of conveying by colour alone are replaced with combining an icon, wording, and shape or text.

7.3. Following a Contrast Theme (High Contrast)

Windows has contrast themes (formerly high contrast) that switch to a colour scheme with a strong separation of foreground and background; the user can select and edit built-in themes designed so that the contrast ratio is generally 7:1 or more.9 The principle on the app side is simple: do not hard-code colours; respect system colours.

  • WinForms: if you leave ForeColor/BackColor at the default, the user’s colour settings are used. Where you have applied a colour of your own, judge with SystemInformation.HighContrast, switch to a SystemColors-based scheme, and follow a settings change with the UserPreferenceChanged event.12
  • WPF/WinUI: if you reference SystemColors-class resources, you follow a theme switch. Places you have filled with a brush of your own become the cause of breakage.9
Following a contrast themePlaces where a colour is hard-coded break on a switch to a contrast theme, so switch to a SystemColors-based scheme and follow with a settings-change event; if you reference system colours you can follow the user's colours automaticallyHard-codedSystem-colour referenceSwitch to a contrast themeHow is the colour specified?The colour scheme breaksAutomatically follows the user's coloursSwitch to SystemColorsFollow with a settings-change event

Figure 14: Only places where a colour is hard-coded break under a contrast theme; a system-colour reference follows automatically.

Also, a user with low vision often uses a high OS magnification (DPI scaling), so high-DPI support is also part of accessibility support. An app whose layout breaks at 125%–200% is unusable at that point. See “High-DPI Support in WinForms” and “WPF High-DPI Support” for the details.

8. Verification in Practice — Accessibility Insights and a Hands-On Screen-Reader Check

8.1. Accessibility Insights for Windows

Microsoft provides Accessibility Insights for Windows as an accessibility verification tool for Windows apps, with three main uses.10

  • Live Inspect: just hover the mouse over an element or keyboard-focus it, and you can confirm its UIA properties (Name, ControlType, patterns, and the like). The shortest means of seeing “what is this button’s Name”.
  • FastPass: a lightweight check that detects high-impact accessibility problems in under five minutes. Problems that can be judged mechanically, such as a missing Name, can be inventoried per new screen.
  • Troubleshooting: assists diagnosis and fixing of a particular problem. From a detected problem you can walk directly to the per-framework fix guides this article also cites.

Inspect.exe and AccEvent, included in the Windows SDK, can also confirm the UIA tree and properties, but they are positioned as legacy tools, and a move to Accessibility Insights is now recommended.10

Three uses of Accessibility InsightsAccessibility Insights for Windows provides confirming UIA properties with Live Inspect, a lightweight check of high-impact problems with FastPass, and assistance with diagnosing and fixing a problem with Troubleshooting; a move from legacy tools such as Inspect.exe is recommendedA move is recommendedAccessibility InsightsLive InspectFastPassTroubleshootingConfirm UIA propertiesDetect high-impact problemsAssist diagnosis and fixingInspect.exe and the like

Figure 15: Accessibility Insights has the three uses of confirm, detect, and diagnose, and is the destination of a move from legacy tools.

8.2. A Hands-On Check with a Screen Reader

What a tool’s automatic check can detect is only problems that can be judged mechanically. In the end, always walk through a real business operation with a screen reader. Windows-built-in Narrator can be started immediately with Ctrl+Windows key+Enter, and NVDA can be introduced for free.11 The trick of the check is to try, without looking at the screen (or with the display off), relying only on the announcement, whether you can complete a real task such as “enter one order and confirm it”. Problems such as a name being present but the announcement order being incoherent, or focus escaping outside a modal, are found only hands-on.

Combining tool verification and a hands-on checkWhat an automatic check such as FastPass can detect is only problems that can be judged mechanically; the remainder is found hands-on by walking through a real business operation with a screen reader and finding announcement-order and focus problemsA tool's automatic checkProblems that can be judged mechanicallyProblems it cannot detect remainA hands-on check with a screen readerWalk through a business operationAnnouncement-order and focus problems

Figure 16: Inventory mechanical problems with an automatic check, and find the remainder with a hands-on check with a screen reader.

8.3. Building It into the Development Flow, and the Mutual Payoff with UI Automated Testing

To keep verification from becoming person-dependent, we recommend building the following checklist into the review items for a new screen.

# Check item Means
1 FastPass with zero errors Accessibility Insights
2 Every input field and button has a Name Live Inspect
3 You can reach every function with the Tab key alone Manual
4 Enter/Esc and the main shortcuts work Manual
5 Text contrast ratio 4.5:1 or more A contrast checker
6 It does not break under a contrast theme Switch the theme and inspect visually
7 It does not break at 200% scaling Change the display setting and inspect visually
8 You can complete a representative task with a screen reader Narrator/NVDA

And one more. UI automated testing with FlaUI and the like is built on the same UIA that screen readers use. The Name and patterns you put in place for accessibility become parts of test code, and an AutomationId designed for tests makes debugging in Live Inspect easier. Conversely, a UI that does not appear in the UIA tree is invisible both to tests and to assistive technology. Accessibility and testability are two sides of the same investment (“UI Automated Testing for Windows Desktop Apps”).

The mutual payoff of accessibility and UI automated testingA screen reader and UI automated testing such as FlaUI are built on the same UIA, so the Name and patterns you put in place can be used from both, and a UI that does not appear in the UIA tree is invisible from eitherPutting the UIA tree in orderA screen reader can read itIt can be used in UI automated testingTwo sides of the same investmentA UI that does not appear in UIAInvisible from either

Figure 17: Because they sit on the same UIA foundation, putting the UIA tree in order pays off for both assistive technology and UI automated testing.

9. How to Set Priorities — Do Not Fix Every Screen at Once

Fixing a core system of hundreds of screens all at once is unrealistic in both cost and quality. The approach we recommend is the following three tiers.

  1. Fix from the screens that user uses in the job. Reasonable accommodation is a process of responding individually to a request from the person concerned.1 First have the person operate the actual job with a screen reader, and identify together where they get stuck. In many cases the screens used in day-to-day work narrow to a few to a dozen, and the fatal problems among them (a button with no name, a confirm button you cannot press from the keyboard) can be resolved in a fix of days.
  2. Make new development standard-compliant. Add Chapter 8’s checklist to the Definition of Done, and build new screens supported from the start. Unlike an after-the-fact fix, the cost increase of building it in at design time is slight.
  3. Roll out sideways by fixing shared controls. If you implement a default AccessibleName or an AutomationPeer on shared in-house parts such as a search dialog, a grid, or a date input, it takes effect in a batch on every screen that uses them. It is a far more cost-effective move than touching individual screens one by one.
The three tiers of fix priorityFix from the screens the user uses in the job, make new development standard-compliant with a checklist, and roll out to every screen by fixing shared controls1. Fix from the screens the user uses2. New work is standard-compliant3. Roll out sideways with shared controlsTakes effect in a batch on every screen that uses them

Figure 18: Advance not by fixing every screen at once but in the three tiers of screens in use, new work, and shared parts.

And a record of the dialogue is as important as the technical response. Reasonable accommodation is a process of “dialoguing and adjusting individually”, not of fully meeting every request. Considering an alternative means with the person (doing that job on another screen, preparing a CSV export, covering it in operations) and agreeing, for a fix whose burden is too heavy, is also a legitimate outcome of constructive dialogue.1 Recording what was requested, what was responded to, and what was made an alternative means becomes the organisation’s proof of good faith.

The flow of constructive dialogue and a recordRespond to a request from a person with a disability through constructive dialogue; carry out a fix that can be responded to; for a fix whose burden is too heavy, consider an alternative means with the person and agree; record what was requested, what was responded to, and what was made an alternative meansNoYesA requestConstructive dialogueIs the burden too heavy?Respond with a fixConsider an alternative means and agreeRecord the history

Figure 19: In constructive dialogue you agree with the person on a fix or an alternative means, and leave that history in a record.

10. Summary

  • With the amended Act for Eliminating Discrimination against Persons with Disabilities that took effect in April 2024, the provision of reasonable accommodation became an obligation for businesses as well. The employment field has been an employer obligation since 2016 under the Act on Employment Promotion of Persons with Disabilities. Making the app easier to use in advance is “environmental improvement” (an effort obligation), and the further it has gone, the lighter individual responses become.
  • The technical criteria are concentrated in WCAG (JIS X 8341-3:2016), and the same thinking can be applied to a desktop app via WCAG2ICT.
  • A screen reader reads an app through UI Automation. The trio of the UIA tree, properties (Name/ControlType/AutomationId), and control patterns is the foundation.
  • The highest priority is Name. WinForms uses AccessibleName and associating a Label with tab order; WPF uses AutomationProperties.Name/LabeledBy; a custom control uses an AutomationPeer.
  • Being able to reach every function from the keyboard alone is a WCAG success criterion and, at the same time, every operator’s productivity. Put tab order, access keys, and focus indication in order.
  • The three basics of colour are a contrast ratio of 4.5:1, colour is not the only means, and respecting system colours in a contrast theme.
  • Combine verification with FastPass+Live Inspect in Accessibility Insights and a hands-on check with Narrator/NVDA, and build it into the development flow as a checklist for a new screen.
  • Do not fix every screen at once; advance in the order screens the user uses → standard support for new work → a sideways roll-out of shared controls. Reasonable accommodation is a process of dialogue, and a record of the history protects the organisation.

As a first step we recommend picking one of your main screens, running FastPass in Accessibility Insights for Windows, and then walking through the job with the Tab key alone. In thirty minutes, the present position of your own app becomes surprisingly concrete.

KomuraSoft LLC handles accessibility fixes of WinForms/WPF business apps (screen-reader support, putting keyboard operation in order, contrast-theme support), implementing an AutomationPeer on shared controls, and consultations on a present-state diagnosis and priority-setting with Accessibility Insights. Starting from the stage of “we want to confirm whether an employee can use our app with a screen reader” is fine.

References

  1. Cabinet Office, Leaflet “From 1 April 2024, the provision of reasonable accommodation became an obligation”. On the Reiwa 3 amendment to the Act for Eliminating Discrimination against Persons with Disabilities taking effect on 1 April Reiwa 6 and the provision of reasonable accommodation by businesses becoming an obligation; on the provision of reasonable accommodation being a response, within a range that is not an excessive burden, to an indication of intent from a person with a disability; on the importance of constructive dialogue and a unilateral refusal potentially constituting a violation of the obligation; on “environmental improvement”, advance improvement measures aimed at an unspecified number of persons with disabilities, being an effort obligation; and on employment and work following the provisions of the Act on Employment Promotion of Persons with Disabilities.  2 3 4 5 6 7 8 9 10

  2. Ministry of Health, Labour and Welfare, The prohibition of discrimination against persons with disabilities in employment and the obligation to provide reasonable accommodation. On the amended Act on Employment Promotion of Persons with Disabilities that took effect in April Heisei 28 obligating employers to prohibit disability discrimination in employment and to provide reasonable accommodation within a range that is not an excessive burden; and on related materials such as the reasonable-accommodation guidelines.  2 3 4

  3. Web Accessibility Infrastructure Committee (WAIC), Understanding JIS X 8341-3:2016. On JIS X 8341-3:2016 being a corresponding standard of ISO/IEC 40500:2012, and the body of the standard being the same content as WCAG 2.0; and on the scope of web content the standard assumes.  2

  4. W3C, Guidance on Applying WCAG 2 to Non-Web Information and Communications Technologies (WCAG2ICT). On the W3C Group Note that shows how to apply the principles, guidelines, and success criteria of WCAG 2.0/2.1/2.2 to non-Web documents and software.  2

  5. Microsoft Learn, UI Automation Specification. On UI Automation providing UI information to assistive technology such as a screen reader and enabling operation by means other than standard input; and on the composition of UIA elements, the tree, properties, control patterns, control types, and events.  2 3

  6. Microsoft Learn, WinForms: Setting the accessible name on a control. On Text being reused as the UIA Name on some controls, while ComboBox, ListBox, ListView, PictureBox, ProgressBar, TabControl, TextBox, TreeView and the like do not reuse it; on placing the target control immediately after a Label’s TabIndex so that the Label’s text is used as Name; and on setting AccessibleName explicitly and the problem of an empty string remaining in the designer file.  2 3 4

  7. Microsoft Learn, WPF: Setting the accessible name on a button. On a Button’s Content being reused as the UIA Name by default; on a screen reader being unable to announce the purpose of a button with no name; and on associating a TextBlock with AutomationProperties.LabeledBy and setting AutomationProperties.Name explicitly.  2 3 4

  8. W3C / Web Accessibility Infrastructure Committee (WAIC) translation, Web Content Accessibility Guidelines (WCAG) 2.1 Japanese translation. On success criterion 1.4.3 (Contrast (Minimum)) of 4.5:1 for text and 3:1 for large text; on success criterion 1.4.1 (Use of Color) of not making colour the only visual means; and on success criterion 2.1.1 (Keyboard) of keyboard operability of all functionality.  2 3 4 5 6

  9. Microsoft Learn, Contrast themes. On contrast themes using a constrained palette of a contrast ratio of generally 7:1 or more; on selecting a built-in theme and editing colours; and on SystemColor-class resources being defined as foreground/background pairs and following a theme switch automatically.  2 3

  10. Microsoft Learn, Accessibility testing. On the three scenarios of Accessibility Insights for Windows — Live Inspect (confirming UIA properties by hover/focus), FastPass (detecting high-impact problems in under five minutes), and Troubleshooting — and on the recommendation to move from legacy tools such as Inspect and AccEvent.  2 3

  11. NVDA Japanese Team, NVDA Japanese edition. On the free, open-source Windows screen reader NVDA and the provision of its Japanese edition.  2

  12. Microsoft Learn, Walkthrough: Creating an Accessible Windows-based Application. On placing a descriptive Label in the immediately preceding tab order of an input field; on an access key via & in Text; on judging high contrast with SystemInformation.HighContrast and using SystemColors; on following the UserPreferenceChanged event; and on combining a visual cue with information conveyed by colour.  2 3

  13. Microsoft Learn, Providing Accessibility Information for Controls. On the AccessibleName, AccessibleDescription, AccessibleRole, and AccessibleDefaultActionDescription properties of a WinForms control and how to set them. 

  14. Microsoft Learn, WPF: Setting the accessible name on an edit field. On a TextBlock’s Text being reused as the UIA Name, while a TextBox’s Text is exposed as UIA Value; and on associating a label TextBlock with a TextBox via AutomationProperties.LabeledBy, or setting AutomationProperties.Name. 

  15. Microsoft Learn, UI Automation of a WPF Custom Control. On a custom control overriding OnCreateAutomationPeer and returning an AutomationPeer-derived class; on inheriting the Peer class that corresponds to the base control; on providing a pattern provider via GetPattern; and on overriding from the XAML side with AutomationProperties attributes.  2

Recent articles sharing the same tags. Deepen your understanding with closely related topics.

These topic pages place the article in a broader service and decision context.

This article connects naturally to the following service pages.

Frequently Asked Questions

Common questions about the topic of this article.

Is accessibility support for a business app required by law?
The 2021 amendment to the Act for Eliminating Discrimination against Persons with Disabilities took effect on 1 April 2024, and the provision of reasonable accommodation to persons with disabilities became an obligation for businesses as well. Reasonable accommodation is a response that, when a person with a disability makes a request, removes an individual barrier within a range that is not an excessive burden; making the app easier to use in advance is positioned as an effort obligation called "environmental improvement". Employment, such as the relationship between an employee and the company, is not under that Act but under the Act on Employment Promotion of Persons with Disabilities, which has obligated employers to provide reasonable accommodation since the amendment that took effect in April 2016. In other words, a situation of "an employee cannot use the business app" has been in the domain of obligation for some time. How far to go in any given case depends on the individual situation, so you confirm primary sources from the Cabinet Office and the Ministry of Health, Labour and Welfare and decide through dialogue with the person concerned.
How does a screen reader read a Windows desktop app?
Screen readers such as Narrator and NVDA read an app's UI through an accessibility foundation called UI Automation (UIA). The app side exposes on-screen elements in a structure called the UIA tree; each element has properties such as Name (purpose) and ControlType (kind), and control patterns such as Invoke (press) and Value (value). The screen reader announces this information as "Confirm order button" and operates through the patterns. Standard WinForms and WPF controls have this mechanism from the start, so the developer's main job is not to leave Name empty, to make the UI operable from the keyboard, and to implement information on custom controls.
On an existing WinForms app, what should we start with?
The shortest path is to run FastPass in Accessibility Insights for Windows against the target screen and inventory controls whose Name is empty and tab-order problems. Fixes start with setting AccessibleName on icon-only buttons, associating a Label in the immediately preceding tab order of an input field, and tidying TabIndex so that it matches the visual order. Then start Narrator or NVDA and walk through a real business operation without looking at the screen, and confirm where you get stuck. You do not need to fix every screen at once; starting from screens that someone actually uses, and making new screens standard-compliant with a checklist, is realistic.
What should we do for high-contrast (contrast theme) support?
The baseline is not to hard-code colours and to respect system colours. In WinForms, leave ForeColor/BackColor at the default or use SystemColors, judge the state with SystemInformation.HighContrast, and follow a switch with the UserPreferenceChanged event. In WPF and WinUI, too, if you reference SystemColors-class resources, you follow a theme switch automatically. At the same time, stop conveying information "by colour alone" — showing an error only in red — and combine it with an icon or wording. Even in the ordinary theme, taking the WCAG criterion of a text contrast ratio of 4.5:1 or more as a guide also makes the UI more readable for a poorly lit shop floor and for older users.
Does accessibility support also help UI automated testing?
It does. UI automated-testing tools such as FlaUI are built on the same UI Automation that screen readers use. The Name, ControlType, and control patterns you put in place for accessibility can be used as-is from test code, and an AutomationId designed for tests stabilises element identification. Conversely, a custom-drawn UI that does not appear in the UIA tree is invisible both to a screen reader and to tests. Accessibility and automated testing are an investment in the same foundation, so putting either in place also lowers the cost of the other.

Author Profile

Profile page for the article author.

Go Komura

Representative of KomuraSoft LLC

Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.

Back to the Blog