2011年7月18日月曜日

wpf RoutedUICommandのKeyGestureで修飾キーがいる/いらない

WPFでコンテキストメニューを使ったプログラムを組んでたときのお話。 MenuItemにRoutedUICommandを登録してショートカットキーを使えるようにしていました。 で、アプリケーション実行中にショートカットキーを変更しようと次のようなコードを書きました。

public readonly static RoutedUICommand FooCommand;
...
void bar_function()
{
    FooCommand.InputGestures.Clear();
    FooCommand.InputGestures.Add(new KeyGesture(Key.A) );
}

Addのところで例外発生です。 どうやらCtrlなどの修飾キーなしでRoutedUICommandにKeyGestureを追加したら例外が発生する仕様らしいですね。 A-Z、数字、記号など押して文字が出る普通のキーは修飾キーとセットで登録しないとなりません。

wpfでアプリケーションを作る場合、ショートカットキーのカスタマイズを実装するには注意する必要があるようです。 Ctrl+Aとかではなく、AキーだけでショートカットにしたいときはRoutedUICommandは使えません。 そういうときは独自にキーイベントを処理するコードを書くことになります。 まぁ、ゲームとかを除くと「Ctrlと一緒なんて絶対だめだ」というようなケースはたいてい思考が固まっているだけなので、何が便利か考え直せばRoutedUICommandでOKになると思います。

ちなみに、コーディングのミスでKeyGesture(Key.Back)とかしたら例外は出ませんでした。 MSDNには「ほとんどの場合、KeyGestureは1つ以上のModifierKeysに関連付けられている必要があります。 この規則の例外は、単独で有効なKeyGestureにできるファンクションキーとテンキーのキーです。」とあるけど、どうやら他にも単独で有効にできるキーはありそうですね。

完全ではないけど修飾キーなしでショートカットとして登録できるキーを調べてみました。 こんな感じになりました。 oは単独でショートカットキーにできます。 xは特殊なキーのためショートカットキーには使用できません。 (修飾キーとセットでも不可)

  • Back … o
  • TAB … o
  • エンター … o(NumPadと共用)
  • Space … o
  • Insert … o
  • Delete … o
  • Home … o
  • End … o
  • PageUp … o
  • PageDown … o
  • PrintScreen … x
  • Scroll … o
  • Pause … o
  • NumLock … o
  • CapsLock … x
  • F1~F12 … o
  • 全角半角 … x(該当キーコード不明)
  • 無変換 … o
  • 前候補/変換 … x(該当キーコード不明)
  • カタカナ/ひらがな … x(該当キーコード不明)
  • テンキー/ … o
  • テンキー* … o
  • テンキー- … o
  • テンキー+ … o
  • テンキーEnter … o(本体のキーと共用)
  • テンキー.(小数点) … o
  • テンキー0-9 … o

一部を除いてショートカットキーに使えるようですね。 ちなみに、テンキーはNumLockした状態で調べました。

今MSDNどおりじゃない状況なわけですが、将来の仕様変更でMSDNどおりになってこれらのキーのショートカットが単体で使えなくなる可能性も有るんですかね?