コントロールにフォーカスがあるときにキーが押されたことを知るには、KeyDown、KeyUp、KeyPressといったイベント(以下、キーイベントと記述)を使用します。ここでは、これらキーイベントの違いと、使い方を説明します。
注意:ここでは、.NET Framework 2.0から追加されたPreviewKeyDownイベントの説明はしません。PreviewKeyDownイベントについては、こちらをご覧ください。
キーが押された時に発生するキーイベントの順番は、次のようになります。
KeyDownとKeyPressイベントは、キーが押された時に発生します。KeyUpイベントは、押されたキーが離された時に発生します。
キーを押し続けている時は、キーが繰り返されるたびにKeyDownとKeyPressイベントが何回も発生します。しかしKeyUpイベントは、キーが離された時の一回だけ発生します。
KeyDownとKeyUpイベントハンドラでは、KeyEventArgsオブジェクトにより、どのキーが押されたかを知ることができます。KeyEventArgsクラスには幾つかのプロパティがありますが、違いが分かりにくいものもあります。以下にKeyEventArgsのプロパティについて説明します。
KeyDataプロパティは、同時に押されている修飾子キー(Ctrlキー、Shiftキー、Altキー)を含めた、押されたキーの情報を表します。キー情報は、Keys列挙値の組み合わせになります。
同時に押されている修飾子キーを除外した、キーボードコードだけを取得するには、KeyCodeプロパティを使います。KeyCodeプロパティの値を整数表現で取得するには、KeyValueプロパティを使います。これは、KeyCodeプロパティの値を整数型にキャストしたものと考えてよいでしょう。
補足:KeyCodeプロパティの値は、KeyDataプロパティの値とKeys.KeyCode値をAND演算した結果と同等です。
同時に押された修飾子キーだけを取得するには、Modifiersプロパティを使用します。Modifiersプロパティの値は、押されている修飾子キーを表すKeys列挙値の組み合わせになります。Ctrlキー、Shiftキー、Altキーそれぞれが押されているかを調べるには、Control、Shift、Altプロパティを使います。
補足:Modifiersプロパティの値は、KeyDataプロパティの値とKeys.Modifiers値をAND演算した結果と同等です。
以下に具体例を挙げて、分かりにくい点をさらに説明しましょう。
例えば、F1キーが押されたかを調べたい場合、次のようなコードは適当でしょうか?
'KeyDownイベントハンドラ Private Sub TextBox1_KeyDown(ByVal sender As Object, _ ByVal e As KeyEventArgs) Handles TextBox1.KeyDown 'F1キーが押されたか調べる If e.KeyData = Keys.F1 Then Console.WriteLine("F1キーが押されました。") End If End Sub
//KeyDownイベントハンドラ private void TextBox1_KeyDown(object sender, KeyEventArgs e) { //F1キーが押されたか調べる if (e.KeyData == Keys.F1) Console.WriteLine("F1キーが押されました。"); }
注意:上記のC#のコードは、このままコピーしただけでは動きません。イベントハンドラをイベントに関連付ける必要があります。この方法については、こちらで説明しています。
このようにした場合、F1キーが修飾子キーなしで押された時だけ「押された」と認識され、それ以外では無効と判断されます。修飾子キーが押されているか否かに関係なく、F1キーが押されたことを調べるには、KeyCodeプロパティを使用します。
'KeyDownイベントハンドラ Private Sub TextBox1_KeyDown(ByVal sender As Object, _ ByVal e As KeyEventArgs) Handles TextBox1.KeyDown 'F1キーが押されたか調べる If e.KeyCode = Keys.F1 Then Console.WriteLine("F1キーが押されました。") End If End Sub
//KeyDownイベントハンドラ private void TextBox1_KeyDown(object sender, KeyEventArgs e) { //F1キーが押されたか調べる if (e.KeyCode == Keys.F1) Console.WriteLine("F1キーが押されました。"); }
どうしてもKeyDataプロパティを使用するならば、KeyDataプロパティとKeys.KeyCodeのAND演算で確かめる方法もあります。
'KeyDownイベントハンドラ Private Sub TextBox1_KeyDown(ByVal sender As Object, _ ByVal e As KeyEventArgs) Handles TextBox1.KeyDown 'F1キーが押されたか調べる If (e.KeyData And Keys.KeyCode) = Keys.F1 Then Console.WriteLine("F1キーが押されました。") End If End Sub
//KeyDownイベントハンドラ private void TextBox1_KeyDown(object sender, KeyEventArgs e) { //F1キーが押されたか調べる if ((e.KeyData & Keys.KeyCode) == Keys.F1) Console.WriteLine("F1キーが押されました。"); }
修飾子キーが押されているかを確認するには、Control、Shift、Altプロパティを使えばよいので、簡単です。しかしKeyCodeプロパティや、Modifiersプロパティを使用してある修飾子キーが押されているかを確認する場合には、ちょっと注意が必要です。Keys列挙体のメンバにはShiftとShiftKeyがありますが、修飾子キーの確認に使用するのは、Shiftの方です。
補足:Keys列挙体のメンバにはさらに、RShiftKeyとLShiftKeyもありますが、私の環境では、KeyDown、KeyUpイベントではこれらのキーを確認できませんでした。
'KeyDownイベントハンドラ Private Sub TextBox1_KeyDown(ByVal sender As Object, _ ByVal e As KeyEventArgs) Handles TextBox1.KeyDown '正しい If (e.Modifiers And Keys.Shift) = Keys.Shift Then Console.WriteLine("Shiftキーが押されています。") End If '間違い If (e.Modifiers And Keys.ShiftKey) = Keys.ShiftKey Then Console.WriteLine("Shiftキーが押されています。") End If End Sub
//KeyDownイベントハンドラ private void TextBox1_KeyDown(object sender, KeyEventArgs e) { //正しい if ((e.Modifiers & Keys.Shift) == Keys.Shift) Console.WriteLine("Shiftキーが押されています。"); //間違い if ((e.Modifiers & Keys.ShiftKey) == Keys.ShiftKey) Console.WriteLine("Shiftキーが押されています。"); }
それではKeys.ShiftKeyは何かということになりますが、これは、KeyCodeプロパティで取得できるキーボードコードです。例えば、Shiftキーが単独で押された場合、KeyCodeプロパティはKeys.ShiftKey値となります。
Shiftキーが単独で押された場合は、さらに面白いことに、修飾子キーとしてもShiftキーが押されたことになるため、KeyDataプロパティは、Keys.ShiftとKeys.ShiftKeyをOR演算した値になります。
KeyPressイベントは、文字のキーが押された時だけ発生します。具体的には、Tabキー、Insertキー、Deleteキー、Homeキー、Endキー、PageUpキー、PageDownキー、ファンクションキー(F1~F12キー)、Altキー、Shiftキー、Ctrlキー、方向キーなどが押された時は発生しません。Enterキー、BackSpaceキー、Escapeキーが押された時は発生します。
押されたキーは、KeyPressEventArgs.KeyCharプロパティで、Char型として取得できます。例えば、'A'キーを押した時のKeyCharプロパティの値は'a'になりますが、Shiftキーを押しながら'A'キーを押した場合は、大文字の'A'になります。
KeyPressイベントの主な用途は、特定のキーの入力を無効にしたり、入力されたキーを変換したりすることです。
KeyPressイベントで特定のキーの入力を無効にする方法は、「TextBoxに数字しか入力できないようにする」で紹介しています。そこで紹介したように、KeyPressEventArgs.HandledプロパティをTrueにすることにより、キー入力を無効にできます。
補足:.NET Framework 2.0からは、KeyDownイベントハンドラでKeyEventArgs.SuppressKeyPressプロパティをTrueにすることによっても、キー入力を無効にすることができます。KeyDownイベントハンドラでSuppressKeyPressプロパティをTrueにすると、KeyPressイベントは発生しなくなります。
入力されたキーを変換するには、KeyCharプロパティに値を設定します。例えば、入力された文字を大文字にしてテキストボックスに表示するには、次のようにします。
'KeyPressイベントハンドラ Private Sub TextBox1_KeyPress(ByVal sender As Object, _ ByVal e As KeyPressEventArgs) Handles TextBox1.KeyPress '入力された文字を大文字にする e.KeyChar = Char.ToUpper(e.KeyChar) End Sub
//KeyPressイベントハンドラ private void TextBox1_KeyPress(object sender, KeyPressEventArgs e) { //入力された文字を大文字にする e.KeyChar = char.ToUpper(e.KeyChar); }
コントロールによっては、矢印、Tab、Enter、Escキーなどが押されてもキーイベントが発生しません。例えば、ボタンコントロールでは、矢印キーの押下をキーイベントで捕捉できません。これらのキーが押されたことを知る方法は、こちらで紹介しています。