屏幕阅读器和硬件系统按钮

屏幕阅读器(如 讲述人)必须能够识别和处理硬件系统按钮事件并向用户传达其状态。 在某些情况下,屏幕阅读器可能需要完全独自处理这些硬件按钮事件,不让它们传播到其他处理程序。

从 Windows 10 版本 2004 开始,UWP 应用程序可以与其他硬件按钮相同的方式侦听和处理 Fn 硬件系统按钮事件。 以前,此系统按钮仅充当其他硬件按钮报告其事件和状态的修饰符。

注释

Fn 按钮的支持是特定于 OEM 的,可以包括功能,如切换/锁定打开或关闭(与按下和按住键组合相比),以及相应的锁定指示灯,这对失明或有视力障碍的用户可能没有帮助。

Fn 按钮事件通过 Windows.UI.Input 命名空间中的新的 SystemButtonEventController 类公开。 SystemButtonEventController 对象支持以下事件:

重要

如果 SystemButtonEventController 已由较高优先级处理程序处理,则无法接收这些事件。

例子

在以下示例中,我们演示如何基于 DispatcherQueue 创建 SystemButtonEventController ,并处理此对象支持的四个事件。

按下 Fn 按钮时,多个受支持的事件通常会触发。 例如,按 Surface 键盘上的 Fn 按钮会同时触发 SystemFunctionButtonPressed、SystemFunctionLockChanged 和 SystemFunctionLockIndicatorChanged。

  1. 在此第一个代码片段中,我们只是包括所需的命名空间并指定一些全局对象,包括 DispatcherQueueDispatcherQueueController 对象,用于管理 SystemButtonEventController 线程。

    然后,我们在注册 SystemButtonEventController 事件处理委托时,指定返回的 事件令牌

    namespace winrt
    {
        using namespace Windows::System;
        using namespace Windows::UI::Input;
    }
    
    ...
    
    // Declare related members
    winrt::DispatcherQueueController _queueController;
    winrt::DispatcherQueue _queue;
    winrt::SystemButtonEventController _controller;
    winrt::event_token _fnKeyDownToken;
    winrt::event_token _fnKeyUpToken;
    winrt::event_token _fnLockToken;
    
  2. 我们还为 SystemFunctionLockIndicatorChanged 事件指定事件令牌,以及一个布尔值用于指示应用程序是否处于“学习模式”(用户只是尝试探索键盘而不执行任何功能操作)。

    winrt::event_token _fnLockIndicatorToken;
    bool _isLearningMode = false;
    
  3. 第三个代码片段包括 SystemButtonEventController 对象支持的每个事件的相应事件处理程序委托。

    每个事件处理程序都会报出已发生的事件。 此外,FunctionLockIndicatorChanged 处理程序还控制应用是否处于“学习”模式(_isLearningMode = true),这可以防止事件冒泡到其他处理程序,并使用户无需实际执行作即可浏览键盘功能。

    void SetupSystemButtonEventController()
    {
        // Create dispatcher queue controller and dispatcher queue
        _queueController = winrt::DispatcherQueueController::CreateOnDedicatedThread();
        _queue = _queueController.DispatcherQueue();
    
        // Create controller based on new created dispatcher queue
        _controller = winrt::SystemButtonEventController::CreateForDispatcherQueue(_queue);
    
        // Add Event Handler for each different event
        _fnKeyDownToken = _controller->FunctionButtonPressed(
            [](const winrt::SystemButtonEventController& /*sender*/, const winrt:: FunctionButtonEventArgs& args)
            {
                // Mock function to read the sentence "Fn button is pressed"
                PronounceFunctionButtonPressedMock();
                // Set Handled as true means this event is consumed by this controller
                // no more targets will receive this event
                args.Handled(true);
            });
    
            _fnKeyUpToken = _controller->FunctionButtonReleased(
                [](const winrt::SystemButtonEventController& /*sender*/, const winrt:: FunctionButtonEventArgs& args)
                {
                    // Mock function to read the sentence "Fn button is up"
                    PronounceFunctionButtonReleasedMock();
                    // Set Handled as true means this event is consumed by this controller
                    // no more targets will receive this event
                    args.Handled(true);
                });
    
        _fnLockToken = _controller->FunctionLockChanged(
            [](const winrt::SystemButtonEventController& /*sender*/, const winrt:: FunctionLockChangedEventArgs& args)
            {
                // Mock function to read the sentence "Fn shift is locked/unlocked"
                PronounceFunctionLockMock(args.IsLocked());
                // Set Handled as true means this event is consumed by this controller
                // no more targets will receive this event
                args.Handled(true);
            });
    
        _fnLockIndicatorToken = _controller->FunctionLockIndicatorChanged(
            [](const winrt::SystemButtonEventController& /*sender*/, const winrt:: FunctionLockIndicatorChangedEventArgs& args)
            {
                // Mock function to read the sentence "Fn lock indicator is on/off"
                PronounceFunctionLockIndicatorMock(args.IsIndicatorOn());
                // In learning mode, the user is exploring the keyboard. They expect the program
                // to announce what the key they just pressed WOULD HAVE DONE, without actually
                // doing it. Therefore, handle the event when in learning mode so the key is ignored
                // by the system.
                args.Handled(_isLearningMode);
            });
    }
    

另请参阅

SystemButtonEventController 类