zoukankan      html  css  js  c++  java
  • (转)响应键盘输入

    (使用 C#/VB/C++ 和 XAML 的 Windows 应用商店应用)

    可以通过使用 C++、C# 或 Visual Basic 为 Windows 构建的 Windows 应用商店应用中的硬件或触摸键盘来响应击键操作。为此,请使用 Windows 8 中提供的键盘事件。

    键盘支持对于辅助功能非常重要,并且能够在没有触摸屏时启用该功能。此外,有了键盘支持,对于那些经常使用键盘的用户来说,你的应用更实用。用户应可以使用 Tab 和箭头键导航应用,使用空格键和 Enter 键激活 UI 元素,并使用键盘快捷方式访问命令。

    有关文本输入的详细信息,请参阅 显示和编辑文本

    路线图: 本主题与其他主题有何关联?请参阅:

    键盘事件

    使用 C++、C# 或 Visual Basic 的 Windows 应用商店应用提供以下键盘事件,硬件和触摸键盘都可能会发生这些事件。

    事件描述
    KeyDown 按下某个键时发生。
    KeyUp 释放某个键时发生。

    键盘事件和焦点

    仅当 UI 中的控件具有输入焦点时才会生成键盘事件。当用户直接单击或点击布局中的一个控件时该控件获得焦点,或者使用 Tab 键进入内容区域内的 Tab 序列。

    也可以调用控件的 Focus 方法来强制使用焦点。当实现快捷键时需要此操作,因为 UI 加载时默认情况下不设置键盘焦点。有关详细信息,请参阅本主题后面部分的快捷键示例

    若要使某个控件接收输入焦点,则必须启用该控件,该控件必须可见并且 IsTabStopHitTestVisible 的属性值必须为 true。这是大多数控件的默认状态。当某个控件具有输入焦点时,该控件可能引发并响应键盘输入事件,如本主题后面部分所述。你也可以通过处理 GotFocusLostFocus 事件来响应接收或丢失焦点的控件。

    默认情况下,控件的 Tab 序列顺序为它们在 XAML 中的顺序。但是,可以使用 TabIndex 属性修改此顺序。有关详细信息,请参阅 实现键盘辅助功能

    键盘事件处理程序

    输入事件处理程序实现提供以下信息的委派:

    • 事件的发送者。发送者报告附加事件处理程序的对象。
    • 事件数据。对于键盘事件,该数据将是 KeyRoutedEventArgs 的一个实例。处理程序的委派为 KeyEventHandler。对于大多数处理程序方案而言,KeyRoutedEventArgs 的最为相关的属性是 Key,并且可能为 KeyStatus
    • OriginalSource。由于键盘事件是路由的事件,因此事件数据提供 OriginalSource。如果有意允许事件通过对象树向上浮生,则 OriginalSource 有时是所涉及的对象而不是发送者。但是,这取决于你的设计。有关如何使用 OriginalSource 而不是发送者的详细信息,请参阅本主题中的“键盘路由事件”部分或 事件和路由事件概述

    附加键盘事件处理程序

    可以为将事件作为成员包含的任何对象附加键盘事件处理程序功能。这包括任何 UIElement 派生类。以下 XAML 示例显示了如何为 GridKeyUp 事件附加处理程序。

    <Grid KeyUp="Grid_KeyUp">
      ...
    </Grid>
    

    也可以在代码中附加事件处理程序。有关详细信息,请参阅 事件和路由事件概述

    定义键盘事件处理程序

    以下示例显示了在上一示例中附加的 KeyUp 事件处理程序的不完整事件处理程序定义。

    1. void Grid_KeyUp(object sender, KeyRoutedEventArgs e)
    2. {
    3.     //handling code here
    4. }
    Private Sub Grid_KeyUp(ByVal sender As Object, ByVal e As KeyRoutedEventArgs)
        'handling code here
    End Sub
    
    void MyProject::MainPage::Grid_KeyUp(
      Platform::Object^ sender,
      Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
    {//handling code here}

    使用 KeyRoutedEventArgs

    所有键盘事件对事件数据均使用 KeyRoutedEventArgsKeyRoutedEventArgs 包含以下属性:

    如果按下某个键,则引发 KeyDown 事件。同样,如果释放某个键,则引发 KeyUp。通常会侦听这些事件以处理特定键值。若要确定按下或释放了哪个键,请检查事件数据中的 Key 值。Key 返回 VirtualKey 值。VirtualKey 枚举包括使用 C++、C# 或 Visual Basic 的 Windows 应用商店应用支持的所有键。

    修改键

    修改键是用户通常与其他键组合而按下的键,如 Ctrl 或 Shift。你的应用可以使用这些组合作为键盘快捷方式来调用应用命令。

    在使用 C++、C# 或 Visual Basic 的 Windows 应用商店应用中,你可以在 KeyDownKeyUp 事件处理程序中使用代码来检测快捷键组合。然后,你可以跟踪感兴趣的修改键的按下状态。当非修改键发生键盘事件时,可以同时检查修改键是否处于按下状态。

    注意  Alt 键由 VirtualKey.Menu 值表示。

    快捷键示例

    以下示例演示如何实现快捷键。在此示例中,用户可以使用 Play、Pause 和 Stop 按钮或 Ctrl+P、Ctrl+A 和 Ctrl+S 键盘快捷键来控制媒体播放。按钮 XAML 通过使用工具提示和按钮标签中的 AutomationProperties 属性来显示快捷键。此自述文档对于增加应用的有用性和辅助功能非常重要。有关详细信息,请参阅 实现键盘辅助功能

    另请注意,加载页面时页面将输入焦点设置为其自身。如果没有此步骤,则不会有控件获得初始输入焦点,并且在用户手动设置输入焦点之前,应用不会引发输入事件(例如,通过 Tab 浏览或单击某个控件)。

    <Grid KeyDown="Grid_KeyDown">
    
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>
    
      <MediaElement x:Name="DemoMovie" Source="xbox.wmv" 
        Width="500" Height="500" Margin="20" HorizontalAlignment="Center" />
    
      <StackPanel Grid.Row="1" Margin="10"
        Orientation="Horizontal" HorizontalAlignment="Center">
    
        <Button x:Name="PlayButton" Click="MediaButton_Click"
          ToolTipService.ToolTip="Shortcut key: Ctrl+P"
          AutomationProperties.AcceleratorKey="Control P">
          <TextBlock>Play</TextBlock>
        </Button>
    
        <Button x:Name="PauseButton" Click="MediaButton_Click"
          ToolTipService.ToolTip="Shortcut key: Ctrl+A" 
          AutomationProperties.AcceleratorKey="Control A">
          <TextBlock>Pause</TextBlock>
        </Button>
    
        <Button x:Name="StopButton" Click="MediaButton_Click"
          ToolTipService.ToolTip="Shortcut key: Ctrl+S" 
          AutomationProperties.AcceleratorKey="Control S">
          <TextBlock>Stop</TextBlock>
        </Button>
    
      </StackPanel>
    
    </Grid>
    
    //showing implementations but not header definitions
    void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
    {
        (void) e;    // Unused parameter
        this->Loaded+=ref new RoutedEventHandler(this,&MainPage::ProgrammaticFocus);
    }
    void MainPage::ProgrammaticFocus(Object^ sender, RoutedEventArgs^ e) {
        this->Focus(Windows::UI::Xaml::FocusState::Programmatic);
    }
    
    void KeyboardSupport::MainPage::MediaButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
    {
        FrameworkElement^ fe = safe_cast<FrameworkElement^>(sender);
        if (fe->Name == "PlayButton") {DemoMovie->Play();}
        if (fe->Name == "PauseButton") {DemoMovie->Pause();}
        if (fe->Name == "StopButton") {DemoMovie->Stop();}
    }
    
    
    void KeyboardSupport::MainPage::Grid_KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
    {
        if (e->Key == VirtualKey::Control) isCtrlKeyPressed = true;
    }
    
    
    void KeyboardSupport::MainPage::Grid_KeyUp(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
    {
        if (e->Key == VirtualKey::Control) isCtrlKeyPressed = true;
        else if (isCtrlKeyPressed) {
            if (e->Key==VirtualKey::P) {
                DemoMovie->Play();
            }
            if (e->Key==VirtualKey::A) {DemoMovie->Pause();}
            if (e->Key==VirtualKey::S) {DemoMovie->Stop();}
        }
    }
    
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        // Set the input focus to ensure that keyboard events are raised.
        this.Loaded += delegate { this.Focus(FocusState.Programmatic); };
    }
    
    private void Grid_KeyUp(object sender, KeyRoutedEventArgs e)
    {
        if (e.Key == VirtualKey.Control) isCtrlKeyPressed = false;
    }
    
    private void Grid_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        if (e.Key == VirtualKey.Control) isCtrlKeyPressed = true;
        else if (isCtrlKeyPressed)
        {
            switch (e.Key)
            {
                case VirtualKey.P: DemoMovie.Play(); break;
                case VirtualKey.A: DemoMovie.Pause(); break;
                case VirtualKey.S: DemoMovie.Stop(); break;
            }
        }
    }
    
    private void MediaButton_Click(object sender, RoutedEventArgs e)
    {
        switch ((sender as Button).Name)
        {
            case "PlayButton": DemoMovie.Play(); break;
            case "PauseButton": DemoMovie.Pause(); break;
            case "StopButton": DemoMovie.Stop(); break;
        }
    }
    
    Private isCtrlKeyPressed As Boolean
    Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
    
    End Sub
    
    Private Sub Grid_KeyUp(sender As Object, e As KeyRoutedEventArgs)
        If e.Key = Windows.System.VirtualKey.Control Then
            isCtrlKeyPressed = False
        End If
    End Sub
    
    Private Sub Grid_KeyDown(sender As Object, e As KeyRoutedEventArgs)
        If e.Key = Windows.System.VirtualKey.Control Then isCtrlKeyPressed = True
        If isCtrlKeyPressed Then
            Select Case e.Key
                Case Windows.System.VirtualKey.P
                    DemoMovie.Play()
                Case Windows.System.VirtualKey.A
                    DemoMovie.Pause()
                Case Windows.System.VirtualKey.S
                    DemoMovie.Stop()
            End Select
        End If
    End Sub
    
    Private Sub MediaButton_Click(sender As Object, e As RoutedEventArgs)
        Dim fe As FrameworkElement = CType(sender, FrameworkElement)
        Select Case fe.Name
            Case "PlayButton"
                DemoMovie.Play()
            Case "PauseButton"
                DemoMovie.Pause()
            Case "StopButton"
                DemoMovie.Stop()
        End Select
    End Sub
    

    注意  在 XAML 中设置 AutomationProperties.AcceleratorKeyAutomationProperties.AccessKey 会提供字符串信息,这可记录用于调用该特定操作的快捷键。该信息由 Microsoft UI 自动化客户端(如讲述人)捕获,且通常直接提供给用户。设置 AutomationProperties.AcceleratorKeyAutomationProperties.AccessKey 不会自行执行任何操作。你将仍需要附加 KeyDownKeyUp 事件的处理程序,以便在你的应用中真正实现键盘快捷键行为。此外,不会自动为访问键提供带下划线的文本效果。如果你希望在 UI 中显示带下划线的文本,则必须明确对助记键中特定键的文本标注下划线,作为嵌入式 Underline 格式。

    键盘路由事件

    有些事件为路由事件,这些事件包括 KeyDownKeyUp。路由事件使用浮升路由策略。浮升路由策略意味着某个事件从子对象开始,然后向上路由到对象树中的连续父对象。这样便提供了处理相同事件以及与相同数据数据交互的另一个机会。

    请考虑以下 XAML 示例,该示例处理一个 Canvas 和两个 Button 对象的 KeyUp 事件。这种情况下,如果在任一 Button 对象拥有焦点的同时释放键,则会引发 KeyUp 事件。然后,该事件向上浮升到父 Canvas

    <StackPanel KeyUp="StackPanel_KeyUp">
      <Button Name="ButtonA" Content="Button A"/>
      <Button Name="ButtonB" Content="Button B"/>
      <TextBlock Name="statusTextBlock"/>
    </StackPanel>
    

    以下示例显示如何为前面示例中对应的 XAML 内容实现 KeyUp 事件处理程序。

    1. void StackPanel_KeyUp(object sender, KeyRoutedEventArgs e)
    2. {
    3.     statusTextBlock.Text = String.Format(
    4.         "The key {0} was pressed while focus was on {1}",
    5.         e.Key.ToString(), (e.OriginalSource as FrameworkElement).Name);
    6. }

    请注意前面的处理程序中的 OriginalSource 属性的用法。此处,OriginalSource 报告引发此事件的对象。该对象不可能是 StackPanel,因为 StackPanel 不是控件,因此无法拥有焦点。只有 StackPanel 中的两个按钮之一可能引发此事件,但是是哪一个按钮呢?如果在父对象上处理此事件,则会使用 OriginalSource 来辨别实际的事件源对象。

    事件数据中的 Handled 属性

    根据你的事件处理策略,你可能希望只有一个事件处理程序对浮升事件进行响应。例如,如果已将特定的 KeyUp 处理程序附加到其中一个 Button 控件,则这是处理该事件的第一次机会。这种情况下,你可能不希望父面板也处理该事件。对于此方案,可以使用事件数据中的 Handled 属性。

    路由事件数据类中的 Handled 属性用于报告之前在事件路由上注册的另一个处理程序已进行操作。这会影响路由事件系统的行为。在事件处理程序中将 Handled 设置为 true 时,该事件停止路由,但不会发送到连续的父元素。

    AddHandler 和 already-handled 键盘事件

    可以使用特殊技术来附加处理程序,该技术对已标记为已处理的事件进行操作。此技术使用 AddHandler 方法来注册处理程序,而不是使用 XAML 属性或特定语言的添加处理程序语法,如在 C# 中的“+=”。此技术的局限性通常是 AddHandler API 带有一个类型为 RoutedEvent 的参数,该参数标识有问题的路由事件。并非所有路由事件都提供 RoutedEvent 标识符,因此此注意事项会影响在 Handled 情况下仍然可以处理哪些路由事件。 KeyDownKeyUp 事件在 UIElement 上拥有路由事件标识符( KeyDownEventKeyUpEvent)。但是,其他事件(如 TextBox.TextChanged)没有路由事件标识符,因此不能使用 AddHandler 技术。

    命令处理

    少量 UI 元素提供对命令的内置支持。命令在其基础实现中使用与输入相关的路由事件。它能够通过调用一个命令处理程序来处理相关的 UI 输入,如某个指针操作或特定加速器键。

    如果命令处理可用于 UI 元素,可以考虑使用它的命令处理 API 代替任何具体的输入事件。有关详细信息,请参阅 ButtonBase.Command

    还可以实现 ICommand 来封装从普通事件处理程序中调用的命令功能。这样即使没有可用的 Command 属性,也能够使用命令。

    文本输入和控件

    某些控件通过自身的处理来对键盘事件作出响应。例如, TextBox 是一个控件,设计用于捕获然后在视觉上显示使用键盘输入的文本。它以自己的逻辑使用 KeyUpKeyDown 来捕获击键,然后,即使在文本实际上已更改的情况下,也还是会引发自己的 TextChanged 事件。

    通常,仍然可以将 KeyUpKeyDown 的处理程序添加到 TextBox 或计划处理文本输入的任何相关控件中。但是,作为其预期设计,一个控件可能并不会对通过键事件指向它的所有键值作出响应。行为特定于每个控件。

    例如, ButtonBaseButton 的基类)处理 KeyUp 以便可以检查空格键或 Enter 键。ButtonBase 认为 KeyUp 等同于按下鼠标左键以引发 Click 事件。事件的这一处理是在 ButtonBase 覆盖虚拟方法 OnKeyUp 时完成的。其实施过程中会将 Handled 设置为 true。如果空格键未接收到自己处理程序的 already-handled 事件,则结果为某个按钮的任意父按钮侦听键事件。

    另一个示例是 TextBoxTextBox 不会将某些键(如箭头键)视为文本,而是视为特定于控件 UI 的行为。TextBox 将这些事件案例标记为已处理。

    自定义控件可以通过重写 OnKeyDown/ OnKeyUp 来为键事件实现自己的相似重写行为。如果你的自定义控件处理特定加速器键或者具有类似于为 TextBox 描述的方案的控件或焦点行为,则应该将该逻辑放置在自己的 OnKeyDown/OnKeyUp 重写中。

    触摸键盘

    文本输入控件提供对触摸键盘的自动支持。当用户将输入焦点设置为使用触摸输入的文本控件时,触摸键盘会自动出现。当输入焦点不在文本控件上时,隐藏触摸键盘。

    当出现触摸键盘时,会自动重新定位你的 UI 以确保可以看见具有焦点的元素。这可能会导致 UI 的其他重要区域移出屏幕。但是,你可以禁用默认行为并在出现触摸键盘时对自己的 UI 进行调整。有关详细信息,请参阅 响应出现屏幕键盘的示例

    如果创建需要文本输入,但并非从标准文本输入控件派生的自定义控件,则可以通过实现正确的 UI 自动化控件模式来添加触摸键盘支持。有关详细信息,请参阅 触摸键盘示例

    按下触摸键盘上的键引发 KeyDownKeyUp 事件,就像在硬件键盘上按下键一样。但是,触摸键盘不会引发 Ctrl+A、Ctrl+Z、Ctrl+X、Ctrl+C 和 Ctrl+V 的输入事件,这些是输入控件中保留的文本操作。

    原文地址:http://technet.microsoft.com/zh-cn/ie/hh868246

  • 相关阅读:
    CloudStack+KVM环境搭建(步骤很详细,说明ClockStack是用来管理虚拟机的)
    CloudStack和OpenStack该如何选择(如果准备选择OpenStack,请做好hack的准备。CloudStack的底层功能已经做的很完善了,更适合商用)
    NancyFx And ReactiveX
    Apache Kafka® is a distributed streaming platform
    C/C++配置
    Win10 专业版 Hyper-V 主机计算服务无法启动
    使用事件和 CQRS 重写 CRUD 系统
    使用Skywalking分布式链路追踪系统
    GraphQL&DSL&API网关
    TomatoLog 是一个基于 .NETCore 平台的产品。
  • 原文地址:https://www.cnblogs.com/czzju/p/2784128.html
Copyright © 2011-2022 走看看