キーボード入力のしくみ
Windows フォームは、Windows メッセージに応答してキーボード イベントを発生させることにより、キーボード入力を処理します。 多くの Windows フォーム アプリケーションは、キーボード イベントを処理することによってキーボード入力を排他的に処理します。 しかし、高度なキーボード入力のシナリオ (キーがコントロールに到達する前にキーを受け取るなど) を実装するためには、キーボード メッセージのしくみについて理解することが必要です。 このトピックでは Windows フォームが認識するキー データの種類について説明し、キーボード メッセージをルーティングする方法について概要を説明します。 キーボード イベントの詳細については、「キーボード イベントの使用」を参照してください。
キーの種類
Windows フォームはキーボード入力を、ビット単位の Keys 列挙値で表現される仮想キー コードとして識別します。 Keys 列挙値を使用すると、入力された一連のキーを組み合わせて単一の値にできます。 これらの値は WM_KEYDOWN および WM_SYSKEYDOWN の Windows メッセージに付随する値になります。 ほとんどの物理的なキー入力は、KeyDown イベントまたは KeyUp イベントを処理することで検出できます。 文字キーは Keys 列挙値のサブセットであり、WM_CHAR および WM_SYSCHAR の Windows メッセージに付随する値になります。 キー入力の組み合わせが文字になった場合は、KeyPress イベントを処理することでその文字を検出できます。 または、Visual Basic プログラミング インターフェイスによって公開される Keyboard を使用して、どのキーが押されたかの判断と、キーの送信を行うという方法もあります。 詳細については、「キーボードへのアクセス (Visual Basic)」を参照してください。
キーボード イベントの順序
先に説明したとおり、コントロール上では 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 が呼び出されます。 |
|
キーボード メソッドのオーバーライド
キーボード メッセージを処理するためにオーバーライドできるメソッドは多数ありますが、どのメソッドを選ぶかが非常に重要です。 次の表に、実行するタスクと、キーボード メソッドをオーバーライドする最善の方法を示します。 メソッドのオーバーライドの詳細については、「Overriding Properties and Methods」を参照してください。
タスク |
方法 |
---|---|
移動キーを受け取って KeyDown イベントを発生させる。 たとえば、テキスト ボックス内で Tab や Return を処理するなど。 |
IsInputKey をオーバーライドします。
メモ
|
コントロールで特別な入力処理や移動処理を実行する。 たとえば、リスト コントロールで方向キーを使用して選択項目を変更するなど。 |
ProcessDialogKey をオーバーライドします。 |
移動キーを受け取って KeyPress イベントを発生させる。 たとえば、スピン ボックス コントロールで方向キーを複数回押して、項目の移動を加速するなど。 |
IsInputChar をオーバーライドします。 |
KeyPress イベントの間に、特別な入力処理や移動処理を実行する。 たとえば、リスト コントロール内で "r" キーを押し続けると、r の文字で始まる項目にスキップするなど。 |
ProcessDialogChar をオーバーライドします。 |
カスタムなニーモニックの処理を実行する。たとえば、ツール バーに配置されたオーナー描画ボタンのニーモニックを処理するなど。 |
ProcessMnemonic をオーバーライドします。 |