【问题标题】:C# : How to detect if screen reader is running?C#:如何检测屏幕阅读器是否正在运行?
【发布时间】:2011-11-10 12:46:07
【问题描述】:

如何检测屏幕阅读器是否正在运行 (JAWS)?

据我所知,在 .NET 4 中,我们可以使用来自 System.Windows.Automation.Provider 命名空间的 AutomationInteropProvider.ClientsAreListening,但是如果我必须为 .NET 2.0 这样做呢?

我试图检查 ClientsAreListening 源代码,它从 UIAutomationCore.dll 库调用外部 RawUiaClientsAreListening 方法。

您对如何在 .NET 2.0 中实现 JAWS 检测有任何想法吗?

【问题讨论】:

  • 很好奇 - 如果您确定屏幕阅读器正在运行,您打算采取哪些不同的做法?请注意,某些非屏幕阅读器应用程序可能会设置 SPI_SCREENREADER 标志,因此您可能会得到误报或误报。理想情况下,您的应用程序应该可以在不需要检查此标志的情况下运行。你真的在检查一般的屏幕阅读器,还是专门检查 JAWS?

标签: c# accessibility ui-automation screen-readers jaws-screen-reader


【解决方案1】:

使用SystemParametersInfo function 传递uiActionSPI_GETSCREENREADER

您需要为此使用P/Invoke,例如:

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;
        }
    }
}

这可能比使用 ClientsAreListening 属性更好,因为此属性似乎对任何自动化客户端都返回 true,而不仅仅是屏幕阅读器。

另见:

您还应该收听WM_SETTINGCHANGE 消息以检测屏幕阅读器是否开始/停止运行。


更新(回应 BrendanMcK 的 cmets):

虽然这从来没有用太多的词明确记录,但看标志的描述我认为这个标志的目的是比较清楚的:

确定屏幕审查实用程序是否正在运行。屏幕审阅实用程序将文本信息定向到输出设备,例如语音合成器或盲文显示器。设置此标志后,应用程序应在以图形方式显示信息的情况下提供文本信息。

这就是说,只要应用程序希望 UI 表现得像 屏幕阅读器 正在运行,应用程序就会设置此标志,无论该应用程序实际上是否是屏幕读者与否

响应这个标志的合适的事情是add text in order to "read" otherwise intuitive UI state to the user。如果需要彻底更改以使您的 UI 屏幕阅读器易于访问,那么您的 UI 对签名用户来说也不是那么直观,可能需要重新考虑。

【讨论】:

  • 请注意,ClientsAreListening 仅告诉您有关主动侦听可访问性事件的可访问性客户端。可能还有其他人仍在使用可访问性 - 例如。抓取 UI 以获取用于语音识别的动词 - 但使用其他方式来确定何时抓取,并且不要监听可访问性事件。简而言之,这个 API 只让你知道你需要发送事件;不是无障碍客户端是否正在运行。
  • @BrendanMcK 相反,SPI_GETSCREENREADER 只是一个由屏幕阅读器设置的标志,用于向其他人指示他们正在运行(无论使用何种方法)
  • @贾斯汀:对;但 SPI_GETSCREENREADER 确实有一些问题。我有点担心 OP 想要做什么来回应旗帜;非屏幕阅读器通常也设置此标志(例如放大镜或语音输入应用程序),因此您不能假设设置此标志的客户端是实际的屏幕阅读器或其他类型的可访问性客户端。并且有一些可访问性客户端可能不会设置此设置。 (...)
  • (...) 这个标志的主要问题是它没有很好地定义(a)什么是屏幕阅读器(相对于其他辅助功能),或者(b)一个应用程序应该或者如果他们检测到设置了标志,则不应这样做。我对原始 qu 的担忧是,理想情况下,可访问性应该“正常工作”,而不是依赖于标志;该标志只应在“最后的手段”场景中使用。
  • 最后的评论 - 如果使用这个标志,不要忘记在顶级 HWND 获得 WM_SETTINGCHANGE 时重新检查它;用户可以启动应用程序,然后在应用程序运行后启动屏幕阅读器。大多数屏幕阅读器用户可能会在整个会话期间运行阅读器 - 您不应该假设 所有 用户都会这样做。 (例如,用户可能与视力正常的同事共享机器,并根据需要启动阅读器,或者可能有中等视力,只是间歇性地使用阅读器。)
猜你喜欢
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
  • 2018-03-27
相关资源
最近更新 更多