キーボード アクセラレータ

Surface キーボードのHero イメージ

アクセラレータ キー (またはキーボード アクセラレータ) は、ユーザーがアプリの UI を移動せずに一般的なアクションやコマンドを呼び出す直感的な方法を提供することで、Windows アプリケーションの使いやすさとアクセシビリティを向上させるキーボード ショートカットです。

注

キーボードは、特定の障碍を持つユーザーにとって不可欠であり ( キーボードのアクセシビリティを参照)、アプリを操作するより効率的な方法として好むユーザーにとって重要なツールでもあります。

キーボード ショートカットを使用して Windows アプリケーションの UI を移動する方法の詳細については、「Access キー」トピックを参照してください。

独自のカスタム キーボード ショートカットを作成するには、「 キーボード イベント 」トピックを参照してください。

概要

アクセラレータは、修飾子と非修飾子の 2 種類のキーで構成されます。 修飾キーには、Shift、Menu、Control、および VirtualKeyModifiers を介して公開される Windows キーが含まれます。 非修飾子には、Delete、F3、Spacebar、Arrow、Esc、およびすべての英数字および句読点キーなど、 任意の VirtualKey が含まれます。

注

通常、アクセラレータには、ファンクション キー F1 から F12、または 1 つ以上の修飾子キー (Ctrl、Shift) と組み合わせた標準キーの組み合わせが含まれます。 たとえば、ユーザーが Ctrl + Shift + M キーを押すと、フレームワークは修飾子 (Ctrl と Shift) をチェックし、アクセラレータが存在する場合はアクセラレータを起動します。

多くの XAML コントロールには、キーボード アクセラレータが組み込まれています。 たとえば、ListView では、リスト内のすべての項目を選択するための Ctrl + A がサポートされ、RichEditBox ではテキスト ボックスに Tab を挿入するための Ctrl + Tab がサポートされます。 これらの組み込みのキーボード アクセラレータは 、コントロール アクセラレータ と呼ばれ、フォーカスが要素またはその子のいずれかにある場合にのみ実行されます。 ここで説明するキーボード アクセラレータ API を使用して定義されたアクセラレータは、 アプリ アクセラレータと呼ばれます。

キーボード アクセラレータはすべてのアクションで使用できるわけではありませんが、多くの場合、メニューで公開されているコマンドに関連付けられます (メニュー項目の内容で指定する必要があります)。 アクセラレータは、同等のメニュー項目がないアクションに関連付けることもできます。 ただし、ユーザーはアプリケーションのメニューに依存して使用可能なコマンド セットを検出して学習するため、アクセラレータの検出を可能な限り簡単に行う必要があります (ラベルまたは確立されたパターンを使用すると、これに役立ちます)。

アクセラレータは自動的に繰り返されます (たとえば、ユーザーが Ctrl + Shift キーを押しながら M キーを押すと、M が離されるまでアクセラレータが繰り返し呼び出されます)。 この動作は変更できません。

メニュー項目ラベルのキーボード アクセラレータのスクリーンショット。
メニュー項目ラベルで説明されているキーボード アクセラレータ

キーボード アクセラレータを使用する場合

UI で適切な場所にキーボード アクセラレータを指定し、すべてのカスタム コントロールでアクセラレータをサポートすることをお勧めします。

  • キーボード アクセラレータを使用すると、一度に 1 つのキーしか押せないユーザーやマウスの使用が困難なユーザーなど、運動障碍のあるユーザーにとってアプリのアクセシビリティが高くなります。

    適切に設計されたキーボード UI は、ソフトウェア アクセシビリティの重要な側面です。 視覚障碍のあるユーザーや、特定の運動障碍を持つユーザーがアプリをナビゲートし、その機能と対話できるようにします。 このようなユーザーはマウスを操作できず、代わりにキーボード拡張ツール、スクリーン キーボード、スクリーン 拡大、スクリーン リーダー、音声入力ユーティリティなどのさまざまな支援技術に依存している可能性があります。 これらのユーザーにとって、包括的なコマンド カバレッジが重要です。

  • キーボード アクセラレータを使用すると、キーボードを操作するパワー ユーザーがアプリをより使いやすくすることができます。

    経験豊富なユーザーは、キーボードベースのコマンドをより迅速に入力でき、キーボードから手を取り除く必要がないため、キーボードの使用を強く好むことがよくあります。 これらのユーザーにとって、効率性と一貫性は非常に重要です。包括性は、最も頻繁に使用されるコマンドに対してのみ重要になります。

キーボード アクセラレータを指定する

Windows アプリでキーボード アクセラレータを作成するには、 KeyboardAccelerator API を使用します。 これらの API を使用すると、押されたキーの組み合わせを検出するために複数の KeyDown イベントを処理する必要がなく、アプリ リソース内のアクセラレータをローカライズできます。

アプリで最も一般的なアクションにキーボード アクセラレータを設定し、メニュー項目のラベルまたはツールヒントを使用してドキュメント化することをお勧めします。 この例では、[名前の変更] コマンドと [コピー] コマンドに対してのみキーボード アクセラレータを宣言します。

<CommandBar Margin="0,200" AccessKey="M">
  <AppBarButton 
    Icon="Share" 
    Label="Share" 
    Click="OnShare" 
    AccessKey="S" />
  <AppBarButton 
    Icon="Copy" 
    Label="Copy" 
    ToolTipService.ToolTip="Copy (Ctrl+C)" 
    Click="OnCopy" 
    AccessKey="C">
    <AppBarButton.KeyboardAccelerators>
      <KeyboardAccelerator 
        Modifiers="Control" 
        Key="C" />
    </AppBarButton.KeyboardAccelerators>
  </AppBarButton>

  <AppBarButton 
    Icon="Delete" 
    Label="Delete" 
    Click="OnDelete" 
    AccessKey="D" />
  <AppBarSeparator/>
  <AppBarButton 
    Icon="Rename" 
    Label="Rename" 
    ToolTipService.ToolTip="Rename (F2)" 
    Click="OnRename" 
    AccessKey="R">
    <AppBarButton.KeyboardAccelerators>
      <KeyboardAccelerator 
        Modifiers="None" Key="F2" />
    </AppBarButton.KeyboardAccelerators>
  </AppBarButton>

  <AppBarButton 
    Icon="SelectAll" 
    Label="Select" 
    Click="OnSelect" 
    AccessKey="A" />
  
  <CommandBar.SecondaryCommands>
    <AppBarButton 
      Icon="OpenWith" 
      Label="Sources" 
      AccessKey="S">
      <AppBarButton.Flyout>
        <MenuFlyout>
          <ToggleMenuFlyoutItem Text="OneDrive" />
          <ToggleMenuFlyoutItem Text="Contacts" />
          <ToggleMenuFlyoutItem Text="Photos"/>
          <ToggleMenuFlyoutItem Text="Videos"/>
        </MenuFlyout>
      </AppBarButton.Flyout>
    </AppBarButton>
    <AppBarToggleButton 
      Icon="Save" 
      Label="Auto Save" 
      IsChecked="True" 
      AccessKey="A"/>
  </CommandBar.SecondaryCommands>

</CommandBar>

キーボードアクセラレータのツールヒントのスクリーンショット。
ツールチップで説明されているキーボード アクセラレータ

UIElement オブジェクトには KeyboardAccelerator コレクション KeyboardAccelerators があり、カスタム KeyboardAccelerator オブジェクトを指定し、キーボード アクセラレータのキーストロークを定義します。

  • キー - キーボード アクセラレータに使用される VirtualKey 。

  • 修飾子 – キーボード アクセラレータで使用する VirtualKeyModifiers 。 修飾子が設定されていない場合、既定値は None です。

注

シングル キー (A、Delete、F2、Spacebar、Esc、マルチメディア キー) アクセラレータとマルチキー アクセラレータ (Ctrl + Shift + M) がサポートされています。 ただし、ゲームパッドの仮想キーはサポートされていません。

スコープ アクセラレータ

一部のアクセラレータは特定のスコープでのみ機能し、他のアクセラレータはアプリ全体で動作します。

たとえば、Microsoft Outlookには次のアクセラレータが含まれています。

  • Ctrl + B、Ctrl + I、ESC は、電子メール送信フォームのスコープでのみ機能します
  • Ctrl + 1 および Ctrl + 2 はアプリ全体で効きます。

コンテキスト メニュー

コンテキスト メニューのアクションは、テキスト エディターで選択した文字やプレイリスト内の曲など、特定の領域または要素にのみ影響します。 このため、コンテキスト メニュー項目のキーボード アクセラレータのスコープをコンテキスト メニューの親に設定することをお勧めします。

ScopeOwner プロパティを使用して、キーボード アクセラレータのスコープを指定します。 このコードでは、スコープ付きキーボード アクセラレータを使用して ListView にコンテキスト メニューを実装する方法を示します。

<ListView x:Name="MyList">
  <ListView.ContextFlyout>
    <MenuFlyout>
      <MenuFlyoutItem Text="Share" Icon="Share"/>
      <MenuFlyoutItem Text="Copy" Icon="Copy">
        <MenuFlyoutItem.KeyboardAccelerators>
          <KeyboardAccelerator 
            Modifiers="Control" 
            Key="C" 
            ScopeOwner="{x:Bind MyList }" />
        </MenuFlyoutItem.KeyboardAccelerators>
      </MenuFlyoutItem>
      
      <MenuFlyoutItem Text="Delete" Icon="Delete" />
      <MenuFlyoutSeparator />
      
      <MenuFlyoutItem Text="Rename">
        <MenuFlyoutItem.KeyboardAccelerators>
          <KeyboardAccelerator 
            Modifiers="None" 
            Key="F2" 
            ScopeOwner="{x:Bind MyList}" />
        </MenuFlyoutItem.KeyboardAccelerators>
      </MenuFlyoutItem>
      
      <MenuFlyoutItem Text="Select" />
    </MenuFlyout>
    
  </ListView.ContextFlyout>
    
  <ListViewItem>Track 1</ListViewItem>
  <ListViewItem>Alternative Track 1</ListViewItem>

</ListView>

MenuFlyoutItem.KeyboardAccelerators 要素の ScopeOwner 属性は、アクセラレータをグローバルではなくスコープとしてマークします (既定値は null またはグローバルです)。 詳細については、このトピックで後述 する「アクセラレータの解決 」セクションを参照してください。

キーボード アクセラレータを呼び出す

KeyboardAccelerator オブジェクトは、UI オートメーション (UIA) コントロール パターンを使用して、アクセラレータが呼び出されたときにアクションを実行します。

UIA [コントロール パターン] は、共通のコントロール機能を公開します。 たとえば、Button コントロールは、Click イベントをサポートする Invoke コントロール パターンを実装します (通常、コントロールは、クリック、ダブルクリック、Enter キー押し、定義済みのキーボード ショートカット、またはその他のキーストロークの組み合わせによって呼び出されます)。 キーボード アクセラレータを使用してコントロールを呼び出すと、XAML フレームワークは、コントロールが Invoke コントロール パターンを実装しているかどうかを調べて、アクティブ化します (KeyboardAcceleratorInvoked イベントをリッスンする必要はありません)。

次の例では、ボタンが呼び出しパターンを実装しているため、Control + S によって Click イベントがトリガーされます。

<Button Content="Save" Click="OnSave">
  <Button.KeyboardAccelerators>
    <KeyboardAccelerator Key="S" Modifiers="Control" />
  </Button.KeyboardAccelerators>
</Button>

要素が複数のコントロール パターンを実装する場合、アクセラレータを介してアクティブ化できるのは 1 つだけです。 コントロール パターンは、次のように優先順位が付きます。

  1. 呼び出し (ボタン)
  2. トグル (チェックボックス)
  3. 選択(リストビュー)
  4. 展開/折りたたみ (コンボボックス)

一致するものが特定されない場合、アクセラレータは無効であり、デバッグ メッセージが表示されます ("このコンポーネントのオートメーション パターンが見つかりませんでした。Invoked イベントに必要なすべての動作を実装します。イベント ハンドラーで Handled を true に設定すると、このメッセージは抑制されます。)

カスタム キーボード アクセラレータの動作

KeyboardAccelerator オブジェクトの Invoked イベントは、アクセラレータの実行時に発生します。 KeyboardAcceleratorInvokedEventArgs イベント オブジェクトには、次のプロパティが含まれています。

  • 処理 ( ブール値): これを true に設定すると、イベントによってコントロール パターンがトリガーされなくなり、アクセラレータ イベントのバブルが停止します。 既定値は false です。
  • 要素 (DependencyObject): アクセラレータに関連付けられているオブジェクト。
  • KeyboardAccelerator: Invoked イベントの発生に使用されるキーボード アクセラレータ。

ここでは、ListView 内の項目のキーボード アクセラレータのコレクションを定義する方法と、各アクセラレータの Invoked イベントを処理する方法を示します。

<ListView x:Name="MyListView">
  <ListView.KeyboardAccelerators>
    <KeyboardAccelerator Key="A" Modifiers="Control,Shift" Invoked="SelectAllInvoked" />
    <KeyboardAccelerator Key="F5" Invoked="RefreshInvoked"  />
  </ListView.KeyboardAccelerators>
</ListView>
void SelectAllInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
  MyListView.SelectAll();
  args.Handled = true;
}

void RefreshInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
  MyListView.SelectionMode = ListViewSelectionMode.None;
  MyListView.SelectionMode = ListViewSelectionMode.Multiple;
  args.Handled = true;
}

既定のキーボード動作をオーバーライドする

一部のコントロールは、フォーカスがあるときに、アプリ定義アクセラレータをオーバーライドする組み込みのキーボード アクセラレータをサポートします。 たとえば、 TextBox にフォーカスがある場合、Control + C アクセラレータは現在選択されているテキストのみをコピーします (アプリ定義アクセラレータは無視され、他の機能は実行されません)。

ユーザーの知識と期待に応じて既定のコントロール動作をオーバーライドすることはお勧めしませんが、コントロールの組み込みのキーボード アクセラレータをオーバーライドできます。 次の例は、PreviewKeyDown イベント ハンドラーを使用して TextBox の Control + C キーボード アクセラレータをオーバーライドする方法を示しています。

private void TextBlock_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
    var ctrlState =
        Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(
            Windows.System.VirtualKey.Control);
    var isCtrlDown =
        ctrlState.HasFlag(Windows.UI.Core.CoreVirtualKeyStates.Down);
    if (isCtrlDown && e.Key == Windows.System.VirtualKey.C)
    {
        // Your custom keyboard accelerator behavior.

        e.Handled = true;
    }
}

キーボード アクセラレータを無効にする

コントロールが無効になっている場合、関連付けられているアクセラレータも無効になります。 次の例では、ListView の IsEnabled プロパティが false に設定されているため、関連付けられている Control + A アクセラレータを呼び出すことはできません。

<ListView >
  <ListView.KeyboardAccelerators>
    <KeyboardAccelerator Key="A"
      Modifiers="Control"
      Invoked="CustomListViewSelecAllInvoked" />
  </ListView.KeyboardAccelerators>
  
  <TextBox>
    <TextBox.KeyboardAccelerators>
      <KeyboardAccelerator 
        Key="A" 
        Modifiers="Control" 
        Invoked="CustomTextSelecAllInvoked" 
        IsEnabled="False" />
    </TextBox.KeyboardAccelerators>
  </TextBox>

<ListView>

親コントロールと子コントロールは、同じアクセラレータを共有できます。 この場合、子にフォーカスがあり、アクセラレータが無効になっている場合でも、親コントロールを呼び出すことができます。

スクリーン リーダーとキーボード アクセラレータ

ナレーターなどのスクリーン リーダーは、キーボード アクセラレータキーの組み合わせをユーザーに読み上げることができます。 既定では、各修飾子 (VirtualModifiers 列挙型の順序) に続いてキーがあり、これらは "+" 記号で区切られています。 これは、 AcceleratorKey AutomationProperties 添付プロパティを使用してカスタマイズできます。 複数のアクセラレータが指定されている場合は、最初のアクセラレータのみが通知されます。

この例では、AutomationProperty.AcceleratorKey は文字列 "Control + Shift + A" を返します。

<ListView x:Name="MyListView">
  <ListView.KeyboardAccelerators>

    <KeyboardAccelerator 
      Key="A" 
      Modifiers="Control,Shift" 
      Invoked="CustomSelectAllInvoked" />
      
    <KeyboardAccelerator 
      Key="F5" 
      Modifiers="None" 
      Invoked="RefreshInvoked" />

  </ListView.KeyboardAccelerators>

</ListView>   

注

AutomationProperties.AcceleratorKey を設定してもキーボード機能は有効になりません。UIA フレームワークにどのキーが使用されるかのみが示されます。

一般的なキーボード アクセラレータ

Windows アプリケーション間でキーボード アクセラレータの一貫性を確保することをお勧めします。

ユーザーはキーボード アクセラレータを記憶し、同じ (または同様の) 結果を期待する必要がありますが、アプリ間の機能の違いにより、これが常に可能であるとは限りません。

編集 一般的なキーボード アクセラレータ
編集モードを開始する Ctrl + E
フォーカスのあるコントロールまたはウィンドウ内のすべての項目を選択する Ctrl + A
検索と置換 Ctrl + H
元に戻す Ctrl + Z
やり直し Ctrl + Y
選択範囲を削除してクリップボードにコピーする Ctrl + X
選択範囲をクリップボードにコピーする Ctrl + C、Ctrl + Insert
クリップボードの内容を貼り付ける Ctrl + V、Shift + Insert
クリップボードの内容を貼り付けます (オプション付き) Ctrl + Alt + V
アイテムの名前を変更する F2
新しいアイテムを追加します。 Ctrl + N
新しいセカンダリ項目を追加する Ctrl + Shift + N
選択したアイテムを削除する (元に戻す) Del、Ctrl + D
選択したアイテムを削除する (元に戻さない) Shift + Del
Bold Ctrl + B
下線 Ctrl + U
斜体 Ctrl + I
ナビゲーション
フォーカスのあるコントロールまたはウィンドウでコンテンツを検索する Ctrl +F
次の検索結果に移動する F3
次の UI ウィンドウに移動する F6
前の UI ウィンドウに移動する Shift + F6
その他のアクション
お気に入りを追加する Ctrl + D
リフレッシュ F5 または Ctrl + R
ズームイン Ctrl + +
縮小します Ctrl + -
既定のビューにズームする Ctrl + 0
セーブ Ctrl + S (保存)
Close Ctrl + W
印刷 Ctrl + P

一部の組み合わせは、ローカライズされたバージョンの Windows では無効であることに注意してください。 たとえば、スペイン語版の Windows では、Ctrl + B の代わりに Ctrl + N が太字で使用されます。 アプリがローカライズされている場合は、ローカライズされたキーボード アクセラレータを提供することをお勧めします。

キーボード アクセラレータのユーザビリティ上のアフォーダンス

ツールヒント

キーボード アクセラレータは通常、Windows アプリケーションの UI で直接説明されないため、ツールヒントを使用して検出可能性を向上させることができます。 ツールヒントは、ユーザーがフォーカスを移動したり、コントロールの上にマウス ポインターを合わせたり、長押ししたりしたときに自動的に表示されます。 ツールヒントは、コントロールにキーボード アクセラレータが関連付けられているかどうか、および関連付けられている場合はアクセラレータ キーの組み合わせを識別できます。

既定では、キーボード アクセラレータが宣言されると、すべてのコントロール ( MenuFlyoutItem と ToggleMenuFlyoutItem を除く) に対応するキーの組み合わせがツールヒントに表示されます。

注

コントロールに複数のアクセラレータが定義されている場合は、最初のアクセラレータのみが表示されます。

Ctrl+S アクセラレータをサポートするツールヒントが上に表示された[保存] ボタンのスクリーンショット
ツールヒントのアクセラレータキーコンボ

Button、AppBarButton、および AppBarToggleButton オブジェクトの場合、キーボード アクセラレータがコントロールの既定のツールヒントに追加されます。 MenuFlyoutItem オブジェクトと ToggleMenuFlyoutItem オブジェクトの場合、キーボード アクセラレータはポップアップ テキストと共に表示されます。

注

ツールヒントを指定すると (次の例の Button1 を参照)、この動作がオーバーライドされます。

<StackPanel x:Name="Container" Grid.Row="0" Background="AliceBlue">
    <Button Content="Button1" Margin="20"
            Click="OnSave" 
            KeyboardAcceleratorPlacementMode="Auto" 
            ToolTipService.ToolTip="Tooltip">
        <Button.KeyboardAccelerators>
            <KeyboardAccelerator  Key="A" Modifiers="Windows"/>
        </Button.KeyboardAccelerators>
    </Button>
    <Button Content="Button2"  Margin="20"
            Click="OnSave" 
            KeyboardAcceleratorPlacementMode="Auto">
        <Button.KeyboardAccelerators>
            <KeyboardAccelerator  Key="B" Modifiers="Windows"/>
        </Button.KeyboardAccelerators>
    </Button>
    <Button Content="Button3"  Margin="20"
            Click="OnSave" 
            KeyboardAcceleratorPlacementMode="Auto">
        <Button.KeyboardAccelerators>
            <KeyboardAccelerator  Key="C" Modifiers="Windows"/>
        </Button.KeyboardAccelerators>
    </Button>
</StackPanel>

Button1、Button2、Button3 というラベルの付いた 3 つのボタンのスクリーンショット。Button2 の上にツール ヒントがあり、Windows + B アクセラレータのサポートが示されています。

Button の既定のツールヒントに追加されたアクセラレータ キーコンボ

<AppBarButton Icon="Save" Label="Save">
    <AppBarButton.KeyboardAccelerators>
        <KeyboardAccelerator Key="S" Modifiers="Control"/>
    </AppBarButton.KeyboardAccelerators>
</AppBarButton>

ディスクのアイコンが付いたボタンのスクリーンショット。ツールチップには、既定の「保存」というテキストの後に、括弧で囲まれたショートカットキー「Ctrl+S」が追加されている。

AppBarButton の既定のツールヒントに追加されたアクセラレータ キーコンボ

<AppBarButton AccessKey="R" Icon="Refresh" Label="Refresh" IsAccessKeyScope="True">
    <AppBarButton.Flyout>
        <MenuFlyout>
            <MenuFlyoutItem AccessKey="A" Icon="Refresh" Text="Refresh A">
                <MenuFlyoutItem.KeyboardAccelerators>
                    <KeyboardAccelerator Key="R" Modifiers="Control"/>
                </MenuFlyoutItem.KeyboardAccelerators>
            </MenuFlyoutItem>
            <MenuFlyoutItem AccessKey="B" Icon="Globe" Text="Refresh B" />
            <MenuFlyoutItem AccessKey="C" Icon="Globe" Text="Refresh C" />
            <MenuFlyoutItem AccessKey="D" Icon="Globe" Text="Refresh D" />
            <ToggleMenuFlyoutItem AccessKey="E" Icon="Globe" Text="ToggleMe">
                <MenuFlyoutItem.KeyboardAccelerators>
                    <KeyboardAccelerator Key="Q" Modifiers="Control"/>
                </MenuFlyoutItem.KeyboardAccelerators>
            </ToggleMenuFlyoutItem>
        </MenuFlyout>
    </AppBarButton.Flyout>
</AppBarButton>

アクセラレータ キーのコンボを含む MenuFlyoutItems を含むメニューのスクリーンショット。
MenuFlyoutItem のテキストに追加されたアクセラレータ キーコンボ

2 つの値を受け入れる KeyboardAcceleratorPlacementMode プロパティを使用して、プレゼンテーションの動作を制御します: 自動 または 非表示。

<Button Content="Save" Click="OnSave" KeyboardAcceleratorPlacementMode="Auto">
    <Button.KeyboardAccelerators>
        <KeyboardAccelerator Key="S" Modifiers="Control" />
    </Button.KeyboardAccelerators>
</Button>

場合によっては、別の要素 (通常はコンテナー オブジェクト) に対してヒントを表示することが必要になる場合があります。

ここでは、KeyboardAcceleratorPlacementTarget プロパティを使用して、[保存] ボタンのキーボード アクセラレータ キーの組み合わせを、ボタンではなく Grid コンテナーと共に表示する方法について説明します。

<Grid x:Name="Container" Padding="30">
  <Button Content="Save"
    Click="OnSave"
    KeyboardAcceleratorPlacementMode="Auto"
    KeyboardAcceleratorPlacementTarget="{x:Bind Container}">
    <Button.KeyboardAccelerators>
      <KeyboardAccelerator  Key="S" Modifiers="Control" />
    </Button.KeyboardAccelerators>
  </Button>
</Grid>

ラベル

場合によっては、コントロールのラベルを使用して、コントロールにキーボード アクセラレータが関連付けられているかどうか、および関連付けられている場合はアクセラレータ キーの組み合わせを識別することをお勧めします。

一部のプラットフォーム コントロールでは、既定でこれを行います。具体的には MenuFlyoutItem オブジェクトと ToggleMenuFlyoutItem オブジェクトが、 AppBarButton オブジェクトと AppBarToggleButton オブジェクトが CommandBar のオーバーフロー メニューに表示されたときに行われます。

メニュー項目ラベルで説明されているキーボード アクセラレータ。
メニュー項目ラベルで説明されているキーボード アクセラレータ

MenuFlyoutItem、ToggleMenuFlyoutItem、AppBarButton、および AppBarToggleButton コントロールの KeyboardAcceleratorTextOverride プロパティを使用して、ラベルの既定のアクセラレータ テキストをオーバーライドできます (テキストなしには 1 つのスペースを使用します)。

注

システムが接続されているキーボードを検出できない場合、オーバーライド テキストは表示されません ( KeyboardPresent プロパティを使用して自分で確認できます)。

高度な概念

ここでは、キーボード アクセラレータのいくつかの低レベルの側面を確認します。

入力イベントの優先度

入力イベントは、アプリの要件に基づいてインターセプトして処理できる特定のシーケンスで発生します。

KeyDown/KeyUp バブリング イベント

XAML では、入力バブル パイプラインが 1 つだけあるかのようにキーストロークが処理されます。 この入力パイプラインは、KeyDown/KeyUp イベントと文字入力によって使用されます。 たとえば、要素にフォーカスがある状態でユーザーがキーを押し下げると、要素で KeyDown イベントが発生し、その後、要素の親要素、そのまた親要素へとツリーの上位に向かってイベントが伝搬します。args.Handled プロパティが true に設定されるまで続きます。

KeyDown イベントは、組み込みのコントロール アクセラレータを実装するために、一部のコントロールでも使用されます。 コントロールにキーボード アクセラレータがある場合、KeyDown イベントが処理されます。つまり、KeyDown イベントのバブルは発生しません。 たとえば、RichEditBox では、Ctrl + C キーを押したコピーがサポートされます。 Ctrl キーを押すと、KeyDown イベントが発生してバブルが発生しますが、ユーザーが C キーを同時に押すと、KeyDown イベントは Handled とマークされ、発生しません ( UIElement.AddHandler の handledEventsToo パラメーターが true に設定されていない場合)。

CharacterReceived イベント

TextBox などのテキスト コントロールの KeyDown イベントの後に CharacterReceived イベントが発生すると、KeyDown イベント ハンドラーで文字入力を取り消すことができます。

PreviewKeyDown イベントと PreviewKeyUp イベント

プレビュー入力イベントは、他のイベントの前に発生します。 これらのイベントを処理しない場合、フォーカスがある要素のアクセラレータ イベントが発生し、続いて KeyDown イベントが発生します。 どちらのイベントも、処理されるまでバブルします。

キーイベントシーケンスを示す図 キーイベントシーケンス

イベントの順序:

KeyDown イベントのプレビュー
…
アプリ アクセラレータ
OnKeyDown メソッド
KeyDown イベント
親オブジェクト上のアプリ アクセラレーター
親の OnKeyDown メソッド
親の KeyDown イベント
(ルートへのバブル)
…
CharacterReceived イベント
PreviewKeyUp イベント
KeyUpEvents

アクセラレータ イベントが処理されると、KeyDown イベントも処理済みとしてマークされます。 KeyUp イベントは未処理のままです。

アクセラレータの解決

キーボード アクセラレータ イベントは、フォーカスされている要素からルート要素まで、バブルが伝播します。 イベントが処理されない場合、XAML フレームワークはバブル パスの外部にある他のスコープ外のアプリ アクセラレータを検索します。

同じキーの組み合わせで 2 つのキーボード アクセラレータが定義されている場合、ビジュアル ツリーで見つかった最初のキーボード アクセラレータが呼び出されます。

スコープ付きキーボード アクセラレータは、フォーカスが特定のスコープ内にある場合にのみ呼び出されます。 たとえば、多数のコントロールを含む Grid では、フォーカスが Grid (スコープ所有者) 内にある場合にのみ、コントロールに対してキーボード アクセラレータを呼び出すことができます。

プログラムでスコープを設定するアクセラレータ

UIElement.TryInvokeKeyboardAccelerator メソッドは、要素のサブツリー内の一致するアクセラレータを呼び出します。

UIElement.OnProcessKeyboardAccelerators メソッドは、キーボード アクセラレータの前に実行されます。 このメソッドは、キー、修飾子、およびキーボード アクセラレータが処理されるかどうかを示すブール値を含む ProcessKeyboardAcceleratorArgs オブジェクトを渡します。 処理済みとしてマークされている場合、キーボード アクセラレータはバブルします (そのため、外部キーボード アクセラレータは呼び出されません)。

注

OnProcessKeyboardAccelerators は、処理されているかどうかに関係なく、常に起動します (OnKeyDown イベントと同様)。 イベントが処理済みとしてマークされたかどうかを確認する必要があります。

この例では、OnProcessKeyboardAccelerators と TryInvokeKeyboardAccelerator を使用して、キーボード アクセラレータのスコープを Page オブジェクトに設定します。

protected override void OnProcessKeyboardAccelerators(
  ProcessKeyboardAcceleratorArgs args)
{
  if(args.Handled != true)
  {
    this.TryInvokeKeyboardAccelerator(args);
    args.Handled = true;
  }
}

アクセラレータをローカライズする

すべてのキーボード アクセラレータをローカライズすることをお勧めします。 これは、XAML 宣言の標準リソース (.resw) ファイルと x:Uid 属性を使用して行うことができます。 この例では、Windows ランタイムによってリソースが自動的に読み込まれます。

リソース ファイルによるキーボード アクセラレータのローカライズを示す図 リソース ファイルを使用したキーボード アクセラレータのローカライズ

<Button x:Uid="myButton" Click="OnSave">
  <Button.KeyboardAccelerators>
    <KeyboardAccelerator x:Uid="myKeyAccelerator" Modifiers="Control"/>
  </Button.KeyboardAccelerators>
</Button>

注

キーボード アクセラレータは仮想キーとして実装されます。 ローカライズされたアクセラレータは、Virtual-Key コード の定義済みのコレクションから選択する必要があります (それ以外の場合は、XAML パーサー エラーが発生します)。

プログラムによるアクセラレータのセットアップ

アクセラレータをプログラムで定義する例を次に示します。

void AddAccelerator(
  VirtualKeyModifiers keyModifiers, 
  VirtualKey key, 
  TypedEventHandler<KeyboardAccelerator, KeyboardAcceleratorInvokedEventArgs> handler )
  {
    var accelerator = 
      new KeyboardAccelerator() 
      { 
        Modifiers = keyModifiers, Key = key
      };
    accelerator.Invoked += handler;
    this.KeyboardAccelerators.Add(accelerator);
  }

注

KeyboardAccelerator は共有できません。同じ KeyboardAccelerator を複数の要素に追加することはできません。

キーボード アクセラレータの動作をオーバーライドする

KeyboardAccelerator.Invoked イベントを処理して、既定の KeyboardAccelerator 動作をオーバーライドできます。

この例では、カスタム ListView コントロールの "すべて選択" コマンド (Ctrl + A キーボード アクセラレータ) をオーバーライドする方法を示します。 また、Handled プロパティを true に設定して、イベントのバブルをさらに停止します。

public class MyListView : ListView
{
  …
  protected override void OnKeyboardAcceleratorInvoked(KeyboardAcceleratorInvokedEventArgs args) 
  {
    if(args.Accelerator.Key == VirtualKey.A 
      && args.Accelerator.Modifiers == KeyboardModifiers.Control)
    {
      CustomSelectAll(TypeOfSelection.OnlyNumbers); 
      args.Handled = true;
    }
  }
  …
}

Samples