Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# : How to detect if screen reader is running?

How to detect if screen reader is running (JAWS)?

As I understand in .NET 4 we can use AutomationInteropProvider.ClientsAreListening from System.Windows.Automation.Provider namespace, but what if I have to do it for .NET 2.0?

I tried to inspect ClientsAreListening source code, it calls external RawUiaClientsAreListening method from UIAutomationCore.dll library.

Do you have any ideas how to implement JAWS detection in .NET 2.0?

like image 733
Jevgenij Nekrasov Avatar asked Oct 10 '22 12:10

Jevgenij Nekrasov


1 Answers

Use the SystemParametersInfo function passing a uiAction of SPI_GETSCREENREADER.

You will need to use P/Invoke for this, for example:

internal class UnsafeNativeMethods
{
    public const uint SPI_GETSCREENREADER = 0x0046;

    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref bool pvParam, uint fWinIni);
}

public static class ScreenReader
{
    public static bool IsRunning
    {
        get
        {
            bool returnValue = false;
            if (!UnsafeNativeMethods.SystemParametersInfo(UnsafeNativeMethods.SPI_GETSCREENREADER, 0, ref returnValue, 0))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "error calling SystemParametersInfo");
            }
            return returnValue;
        }
    }
}

This is possibly better than using the ClientsAreListening property as this property appears to return true for any automation client, not just screen readers.

Also see:

  • Using SystemParametersInfo from C# (SPI_GETSCREENREADER SPI_SETSCREENREADER) (Stack Overflow)
  • INFO: How Clients and Servers Should Use SPI_SETSCREENREADER and SPI_GETSCREENREADER (Microsoft KB)

You should also listen for the WM_SETTINGCHANGE message to detect if a screen reader starts / stops running.


Update (in response to BrendanMcK's comments):

Although this is never explicitly documented in as many words, looking at the description of the flag I think the purpose of this flag is relatively clear:

Determines whether a screen reviewer utility is running. A screen reviewer utility directs textual information to an output device, such as a speech synthesizer or Braille display. When this flag is set, an application should provide textual information in situations where it would otherwise present the information graphically.

What this is saying is that applications set this flag whenever an application wishes the UI to behave as if a screen reader is running, regardless of whether or not that application is actually a screen reader or not.

Suitable things to do in response to this flag is to add text in order to "read" otherwise intuitive UI state to the user. If radical changes are needed to make your UI screen reader accessible then the chances are that your UI also isn't that intuitive to sigted users and could probably do with a re-think.

like image 185
Justin Avatar answered Oct 13 '22 09:10

Justin