そこそこ、複雑なアプリケーションで、ショートカットキーを正しく処理する方法は意外に難解です。単純なアプリケーション用のより簡単な方法は c# ショートカットキーを正しく処理するには? (その3) をご覧ください。
この方法は、c# ショートカットキーを正しく処理するには? (その1) にくらべると、コードのわかりやすさでは劣りますが、使いやすいかもしれません。
ショートカットキーは、Form の ToolStripMenuItem の ShortcutKeys で指定します。デザイナーでビジュアルに指定できるので簡単です。この方法では、修飾子なしのショートカットキーが指定できないので、それらのキーは、Form の ProcessCmdKey をオーバーライドして処理します。ProcessCmdKey で処理を打ち切る場合には、true を、続ける場合には、base.ProcessCmdKey を呼び、その値を返します。
ShortcutKeys で指定したキーは、base.ProcessCmdKey で処理されます。メニューに処理させない場合やできない場合に、テキストだけ表示させるには、ShortcutKeyDisplayString を使います。
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (keyData == Keys.Escape) // ESC 単独 Clipboard.Clear(); return base.ProcessCmdKey(ref msg, keyData); }
アプリケーションが複数のビューからなり、フォーカスのあるビューによってショートカットの挙動を変えるには、各ビューのメニューや、ProcessCmdKey に Form と同様の処理を書けば OK です。
フォーカスのあるコントロールの ProcessCmdKey が最初に呼ばれるため、フォーカスにより挙動を変化させることができます。base.ProcessCmdKey により、親の ProcessCmdKey が呼ばれ、最終的には、 Form の ProcessCmdKey が呼ばれます。
例えば、ショートカットキーに Ctrl+V を使用している場合、ProcessCmdKey により、コンボボックス本来の機能がオーバーライドされます。コンボボックスフォーカス時に、本来の動作を行わせるには、以下のようにします。
コンボボックスの、 PreviewKeyDown イベントで、キーを調べ、Ctrl+V などで、 PreviewKeyDownEventArgs.IsInputKey を true に設定します。true に設定すべきキーは、Ctrl+C、Ctrl+V、Ctrl+X、Ctrl+Z、Ctrl+Insert、Shift+Insert、Shift+Delete、Alt+Back です。
Ctrl や Shift などの修飾の無いアクセラレーターキーを定義したい場合には、修飾子が無い場合、F1~F24、Escape 以外で、true を設定すると良いでしょう。
また、Ctrl+A はディフォルトでは処理されないようですが、ここで SelectAll() してから、true を返すことで実現できます。
コンボボックスだけでなく、コントロールで必要なキーをショートカットキーで使用している場合には、それらのコントロールの PreviewKeyDown イベントでも同様の処理を行います。
その1 では、コンボボックスで本来の挙動を行うために、コンボボックスの派生クラスを作って、ProcessCmdKey をオーバーライドしています。派生クラスを作成する分、コードは増えますが、再利用性は高いと言えます。
こちらの方法でも、 PreviewKeyDown イベントの代わりに、 OnPreviewKeyDown メソッドを使うことで、再利用性を高めることは可能ですが、ProcessCmdKey を利用した方が、一貫性があるのでよりわかりやすいと思います。
派生しなくても、イベントハンドラをライブラリ化して、結びつけて使えば再利用性は高まりますね。あんまり美しくはありませんが、現実的にはよい方法かもしれません。
IsInputKey は、PreviewKeyDown の PreviewKeyDownEventArgs.IsInputKey と似てますが、挙動がかなり違います。
PreviewKeyDown は、 PreProcessMessage よりも先に呼ばれ、引数の IsInputKey を true に設定すると、 PreProcessMessage、ProcessCmdMessage、ProcessDialogMessage は呼ばれません。
一方、IsInputKey では、true を返すと、ProcessDialogMessage は呼ばれなくなりますが、ProcessCmdMessage は呼ばれます。
このサイトのページへのリンクは自由に行っていただいてかまいません。
このサイトで公開している全ての画像、プログラム、文書の無断転載を禁止します。
ここをクリック
すると表示されるページから作者へメールで連絡できます。