キーボード入力のしくみ
更新 : 2007 年 11 月
Windows フォームは、Windows メッセージに応答してキーボード イベントを発生させることにより、キーボード入力を処理します。多くの Windows フォーム アプリケーションは、キーボード イベントを処理することによってキーボード入力を排他的に処理します。しかし、高度なキーボード入力のシナリオ (キーがコントロールに到達する前にキーを受け取るなど) を実装するためには、キーボード メッセージのしくみについて理解することが必要です。このトピックでは Windows フォームが認識するキー データの種類について説明し、キーボード メッセージをルーティングする方法について概要を説明します。キーボード イベントの詳細については、「キーボード イベントの使用」を参照してください。
キーの種類
Windows フォームはキーボード入力を、ビット単位の Keys 列挙値で表現される仮想キー コードとして識別します。Keys 列挙値を使用すると、入力された一連のキーを組み合わせて単一の値にできます。これらの値は WM_KEYDOWN および WM_SYSKEYDOWN の Windows メッセージに付随する値になります。ほとんどの物理的なキー入力は、KeyDown イベントまたは KeyUp イベントを処理することで検出できます。文字キーは Keys 列挙値のサブセットであり、WM_CHAR および WM_SYSCHAR の Windows メッセージに付随する値になります。キー入力の組み合わせが文字になった場合は、KeyPress イベントを処理することでその文字を検出できます。または、Visual Basic プログラミング インターフェイスによって公開される Keyboard を使用して、どのキーが押されたかの判断と、キーの送信を行うという方法もあります。詳細については、「キーボードへのアクセス」を参照してください。
キーボード イベントの順序
先に説明したとおり、コントロール上では 3 つのキーボード関連のイベントが発生します。イベントは一般に次の順序で発生します。
ユーザーが "a" のキーを押すと、キーが前処理され、ディスパッチされて、KeyDown イベントが発生します。
ユーザーが "a" のキーを押し続けると、キーが前処理され、ディスパッチされて、KeyPress イベントが発生します。
このイベントはユーザーがキーを押し続けているとき複数回発生します。
ユーザーが "a" のキーを離すと、キーが前処理され、ディスパッチされて、KeyUp イベントが発生します。
キーの前処理
他のメッセージと同様に、キーボード メッセージもフォームやコントロールの WndProc メソッドで処理されます。ただし、キーボード メッセージが処理される前に、PreProcessMessage メソッドが 1 つ以上のメソッドを呼び出します。これらのメソッドをオーバーライドすることで、特別な文字キーと物理キーの処理が可能になります。これらのメソッドをオーバーライドすると、コントロールがメッセージを処理する前に、特定のキーを検出してフィルタできます。次の表に、実行される処理と、そのとき呼び出されるメソッドを (メソッドが呼び出される順に) 示します。
KeyDown イベントの前処理
アクション |
メソッド |
備考 |
---|---|---|
アクセラレータやメニュー ショートカットなどのコマンド キーの確認。 |
このメソッドはコマンド キーを処理します。コマンド キーは通常のキーよりも優先順位が上です。このメソッドが true を返した場合、キー メッセージはディスパッチされず、キー イベントも発生しません。false を返した場合は、IsInputKey が呼び出されます。 |
|
前処理を必要とする特別なキーか、または KeyDown イベントを発生させ、コントロールにディスパッチされる通常の文字キーかどうかの確認。 |
メソッドが true を返した場合は、コントロールが通常の文字であることを意味するため、KeyDown イベントが発生します。false を返した場合は、ProcessDialogKey が呼び出されます。
メモ :
コントロールがキーまたはキーの組み合わせを確実に取得するためには、PreviewKeyDown イベントを処理し、そのキーの PreviewKeyDownEventArgs の IsInputKey に true を設定します。
|
|
キーが移動キー (Esc、Tab、Return、または方向キー) かどうかの確認。 |
このメソッドはコントロール内で特別な機能 (コントロールとその親コントロールの間のフォーカスの切り替えなど) を実行する物理キーを処理します。このコントロールがキーを処理しない場合は、親コントロールで ProcessDialogKey が呼び出されます。それでも処理しなければ、コントロールの呼び出しが階層構造の最上階のコントロールまで続けられます。このメソッドが true を返した場合、前処理は完了し、キー イベントは生成されません。false を返した場合は、KeyDown イベントが発生します。 |
KeyPress イベントの前処理
アクション |
メソッド |
備考 |
---|---|---|
キーがコントロールによって処理される通常の文字であるかどうかの確認 |
文字が通常の文字である場合は、このメソッドが true を返し、KeyPress イベントが発生します。それ以上の処理は行われません。通常の文字でない場合は、ProcessDialogChar が呼び出されます。 |
|
文字がニーモニック (ボタン上の &OK など) かどうかの確認 |
このメソッドも ProcessDialogKey と同様に、コントロールの階層構造を上に移動しながら呼び出されます。コントロールがコンテナ コントロールである場合は、自身とその子コントロールから ProcessMnemonic を呼び出すことによってニーモニックを確認します。ProcessDialogChar が true を返した場合、KeyPress イベントは発生しません。 |
キーボード メッセージの処理
キーボード メッセージは、フォームまたはコントロールの WndProc メソッドに到達した後、オーバーライド可能な一連のメソッドによって処理されます。これらの各メソッドは、キーボード メッセージが処理され、コントロールがそれを使用したかどうかを示す Boolean 値を返します。いずれかのメソッドが true を返した場合は、メッセージが処理されたと判断されるため、ベース コントロールまたは親コントロールにメッセージが渡されることはありません。そうでない場合は、メッセージがメッセージ キューに残り、場合によってはそのコントロールのベースまたは親に含まれる別のメソッドで処理されます。次の表に、キーボード メッセージを処理するメソッドを示します。
メソッド |
備考 |
---|---|
このメソッドは、コントロールの WndProc メソッドが受信するすべてのキーボード メッセージを処理します。 |
|
このメソッドは、キーボード メッセージを親コントロールに送信します。ProcessKeyPreview が true を返した場合、キー イベントは生成されません。そうでない場合は ProcessKeyEventArgs が呼び出されます。 |
|
キーボード メソッドのオーバーライド
キーボード メッセージを処理するためにオーバーライドできるメソッドは多数ありますが、どのメソッドを選ぶかが非常に重要です。次の表に、実行するタスクと、キーボード メソッドをオーバーライドする最善の方法を示します。メソッドのオーバーライドの詳細については、「プロパティとメソッドのオーバーライド」を参照してください。
タスク |
メソッド |
---|---|
移動キーを受け取って KeyDown イベントを発生させる。たとえば、テキスト ボックス内で Tab や Return を処理するなど。 |
IsInputKey をオーバーライドします。 |
コントロールで特別な入力処理や移動処理を実行する。たとえば、リスト コントロールで方向キーを使用して選択項目を変更するなど。 |
ProcessDialogKey をオーバーライドします。 |
移動キーを受け取って KeyPress イベントを発生させる。たとえば、スピン ボックス コントロールで方向キーを複数回押して、項目の移動を加速するなど。 |
IsInputChar をオーバーライドします。 |
KeyPress イベントの間に、特別な入力処理や移動処理を実行する。たとえば、リスト コントロール内で "r" キーを押し続けると、r の文字で始まる項目にスキップするなど。 |
ProcessDialogChar をオーバーライドします。 |
カスタムなニーモニックの処理を実行する。たとえば、ツール バーに配置されたオーナー描画ボタンのニーモニックを処理するなど。 |
ProcessMnemonic をオーバーライドします。 |