DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

コントロールでキーが押されたことを知る

コントロールにフォーカスがあるときにキーが押されたことを知るには、KeyDown、KeyUp、KeyPressといったイベント(以下、キーイベントと記述)を使用します。ここでは、これらキーイベントの違いと、使い方を説明します。

注意:ここでは、.NET Framework 2.0から追加されたPreviewKeyDownイベントの説明はしません。PreviewKeyDownイベントについては、こちらをご覧ください。

キーイベントの発生する順番

キーが押された時に発生するキーイベントの順番は、次のようになります。

  1. KeyDown
  2. KeyPress
  3. KeyUp

どのような時に発生するか?

KeyDownとKeyPressイベントは、キーが押された時に発生します。KeyUpイベントは、押されたキーが離された時に発生します。

キーを押し続けている時は、キーが繰り返されるたびにKeyDownとKeyPressイベントが何回も発生します。しかしKeyUpイベントは、キーが離された時の一回だけ発生します。

KeyDownと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キーが押されたかを調べたい場合、次のようなコードは適当でしょうか?

VB.NET
コードを隠すコードを選択
'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
C#
コードを隠すコードを選択
//KeyDownイベントハンドラ
private void TextBox1_KeyDown(object sender, KeyEventArgs e)
{
    //F1キーが押されたか調べる
    if (e.KeyData == Keys.F1)
        Console.WriteLine("F1キーが押されました。");
}
注意:上記のC#のコードは、このままコピーしただけでは動きません。イベントハンドラをイベントに関連付ける必要があります。この方法については、こちらで説明しています。

このようにした場合、F1キーが修飾子キーなしで押された時だけ「押された」と認識され、それ以外では無効と判断されます。修飾子キーが押されているか否かに関係なく、F1キーが押されたことを調べるには、KeyCodeプロパティを使用します。

VB.NET
コードを隠すコードを選択
'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
C#
コードを隠すコードを選択
//KeyDownイベントハンドラ
private void TextBox1_KeyDown(object sender, KeyEventArgs e)
{
    //F1キーが押されたか調べる
    if (e.KeyCode == Keys.F1)
        Console.WriteLine("F1キーが押されました。");
}

または、KeyCodeプロパティを使わずに、KeyDataプロパティとKeys.F1のAND演算で確かめる方法もあります。

VB.NET
コードを隠すコードを選択
'KeyDownイベントハンドラ
Private Sub TextBox1_KeyDown(ByVal sender As Object, _
        ByVal e As KeyEventArgs) Handles TextBox1.KeyDown
    'F1キーが押されたか調べる
    If (e.KeyData And Keys.F1) = Keys.F1 Then
        Console.WriteLine("F1キーが押されました。")
    End If
End Sub
C#
コードを隠すコードを選択
//KeyDownイベントハンドラ
private void TextBox1_KeyDown(object sender, KeyEventArgs e)
{
    //F1キーが押されたか調べる
    if ((e.KeyData & Keys.F1) == Keys.F1)
        Console.WriteLine("F1キーが押されました。");
}

ある修飾子キーが押されているかを確認する

修飾子キーが押されているかを確認するには、Control、Shift、Altプロパティを使えばよいので、簡単です。しかしKeyCodeプロパティや、Modifiersプロパティを使用してある修飾子キーが押されているかを確認する場合には、ちょっと注意が必要です。Keys列挙体のメンバにはShiftとShiftKeyがありますが、修飾子キーの確認に使用するのは、Shiftの方です。

補足:Keys列挙体のメンバにはさらに、RShiftKeyとLShiftKeyもありますが、私の環境では、KeyDown、KeyUpイベントではこれらのキーを確認できませんでした。
VB.NET
コードを隠すコードを選択
'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
C#
コードを隠すコードを選択
//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イベントについて

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プロパティに値を設定します。例えば、入力された文字を大文字にしてテキストボックスに表示するには、次のようにします。

VB.NET
コードを隠すコードを選択
'KeyPressイベントハンドラ
Private Sub TextBox1_KeyPress(ByVal sender As Object, _
        ByVal e As KeyPressEventArgs) Handles TextBox1.KeyPress
    '入力された文字を大文字にする
    e.KeyChar = Char.ToUpper(e.KeyChar)
End Sub
C#
コードを隠すコードを選択
//KeyPressイベントハンドラ
private void TextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    //入力された文字を大文字にする
    e.KeyChar = char.ToUpper(e.KeyChar);
}

キーイベントが発生しないキーが押されたことを知る

コントロールによっては、矢印、Tab、Enter、Escキーなどが押されてもキーイベントが発生しません。例えば、ボタンコントロールでは、矢印キーの押下をキーイベントで捕捉できません。これらのキーが押されたことを知る方法は、こちらで紹介しています。

  • 履歴:
  • 2010/6/28 KeyDataプロパティとKeys.F1のAND演算で確認する方法のC#のコードで、KeyDataとすべきところがKeyCodeになっていたのを修正。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。