#11 キーボード関連イベントの違い

ここに出てくるイベント
  • KeyDown/キークリック時
  • KeyUp/キー解放時
  • KeyPress/キー入力時


Accessのフォームでは、GUI環境ということから、どちらかといえばマウス操作が中心で、キーボード関連のイベントを使うことは比較的少ないかもしれません。しかし、データそのものはやはりキーボードからの入力が中心となりますし、マウスを使わない、より能率的なデータ入力や操作性を求められることも少なくありません。
そこでここでは、そのような場合に必要となる知識の1つとして、Accessのフォームに配置されたテキストボックスを例にとって、各種のキーボード関連イベントの内容を整理してみたいと思います。特に、キーボード関連イベントは、以下のように、名前だけではその具体的な意味合いや動作の違いがよく分かりません。そこで、これらのイベントにはどのような違いがあるのか、どのように使い分けたらよいのかを中心に説明を進めていきたいと思います。
  • キークリック時
  • キー解放時
  • キー入力時


キーボード関連イベントの発生をトレースしてみる

それではまず、例によってキーボード関連イベントをトレースするために、新規フォームを作成し、1つのテキストボックスを配置、そのイベントプロパティを以下のように設定します。
テスト用フォームのデザイン

テキストボックスのイベントプロパティ


それでは、早速このフォームを開いて、テキストボックスに何らかのデータを入力してみましょう。

まず、1文字「A」という半角英字を入力してみます。
Aを入力したところ

その結果をイミディエイトウィンドウで確認すると次のようになりました。

発生順序 オブジェクト名 イベント名
1 テキストボックス キークリック時
2 テキストボックス キー入力時
3 テキストボックス キー解放時


ご覧のように、1文字の入力によってキーボード関連のイベント3つがすべて連続して発生してます。これは、続けて任意の文字を1文字ずつ入力していけば分かりますが、常にこの3つがセットで発生するようになっています。

しかしこれでは3つのイベントの違いはまったく分かりません。しかしよく考えてみると、キー入力と一言でいっても、細かい動作分析を行ってみれば、「キーを押し下げる→キーから指を離す」という2つの動作から成り立っていることが分かると思います。イベント名を見ると、何となく、キーボードを押したときや離したときそれぞれでイベントが発生しているようにも思われます。そこで今度は、「A」という文字の入力をすぐに行ってしまわずに、「A」というキーを押し下げて、ほんのちょっと待ってからキーを離すという操作を行ってみましょう。

これは目を凝らしてイミディエイトウィンドウを見ないと分からないのですが、結果から次のようなことが分かりました。
  • キーを押すと、"キークリック時"イベントと"キー入力時"イベントが連続して発生する
  • キーを離すと"キー解放時"イベントが発生する

この結果から、"キーを押し下げる"という操作によって、"キーを押す"という処理と"データが入力される"という2つの処理が1セットとなって実行されているということが分かります。イベントの発生順だけの判断では、これ以上この2つのイベントを分解して考えることはできないようです。その証拠に、「1つのキーを押し続ける」という操作を行ってみましょう。
1つのキーを押しつづけた状態



発生順序 オブジェクト名 イベント名
1 テキストボックス キークリック時
2 テキストボックス キー入力時
3 テキストボックス キークリック時
4 テキストボックス キー入力時
5 テキストボックス キークリック時
6 テキストボックス キー入力時
7 テキストボックス キークリック時
8 テキストボックス キー入力時
9 テキストボックス キークリック時
10 テキストボックス キー入力時
11 テキストボックス キークリック時
12 テキストボックス キー入力時
13 テキストボックス キークリック時
14 テキストボックス キー入力時
15 テキストボックス キー解放時


ご覧のように、"キークリック時"イベントと"キー入力時"イベントが交互に発生し、その1サイクルごとにテキストボックスに1文字が入力されていくことが分かります。そして最後にキーを離したときに1度だけ、"キー解放時"イベントが発生していることも分かります。



特殊なキーを押したときには?

上記のテストでは、「A」や「1」といった、一般にデータとして入力されるキーだけを操作してみました。しかし、キーボードにあるのはこれら英数字だけではありません。そこでここでは、DeleteキーやHomeキー、あるいは矢印キー、ファンクションキーといった特殊なキーを押したときにどうなるか確認してみたいと思います。

ここではまず、下図のように、テキストボックスに「123456」というデータが入力されており、カーソルが「6」の右側にある状態からイベントのトレースを開始してみます。
テスト開始前の状態


この状態から、次のような手順でキー操作を行ってみます。
  1. まず矢印キーの「←」を押してカーソルを「5」と「6」の間に移動させます
  2. 続いてDeleteキーを押して「6」を削除します
  3. 続いてHomeキーを押してカーソルをテキストボックスの先頭に移動させます
  4. 最後に「F4」キーを押してみます(F4キーの意味は特にありません)

そのイベント発生結果は次のようなものになりました。

発生順序 オブジェクト名 イベント名
1 テキストボックス キークリック時
2 テキストボックス キー解放時
3 テキストボックス キークリック時
4 テキストボックス キー解放時
5 テキストボックス キークリック時
6 テキストボックス キー解放時
7 テキストボックス キークリック時
8 テキストボックス キー解放時


ここでは、発生順序の1と2が「←」キーを押して離したときの結果、3と4が「Delete」キー押して離したときの結果というように、常に"キークリック時"イベントと"キー解放時"イベントの2つだけがセットで発生しています。つまり、これらの特殊キーの操作では"キー入力時"イベントは発生しないということが分かります。



3つのイベントをどのように使い分けるか?

それでは、上記の結果を踏まえて、3つのイベントの使い分けを考えてみましょう。

上記の結果を整理すると次のようなことが分かります。
  • いかなるキーについても、押し下げ操作を行うと"キークリック時"イベントが発生する
  • 英数字などのデータ入力を行ったときのみ"キー入力時"イベントが発生する
  • いかなるキーについても、キーを離すと"キー解放時"イベントが発生する
  • "キークリック時"および"キー入力時"イベントは、あるキーを押しっ放しにした場合にも1文字ずつに発生する
  • "キー解放時"イベントは、あるキーを押しっ放しにした場合には最後に1度だけ発生する

これらのことから、どのような処理をしたいときにどのイベントを使えばよいかをまとめると、次のようになると思います。
  • 特殊キーも含めたすべてのキー操作をトラップしたい場合には"キークリック時"イベントを使う

  • 英数字などのデータ入力だけをトラップしたい場合には"キー入力時"イベントを使う

  • 同じキーが連続入力された場合でも、1度だけの入力後処理を行いたい場合には"キー解放時"イベントを使う



3つのイベントプロシージャをどのように使い分けるか?

続いて、イベントプロシージャのコーディングにおける観点から、3つのイベントの使い分けを考えてみましょう。各イベントプロシージャの宣言を見てみると次のようになっています。なお、これらは「txtTest」という名前のテキストボックスのイベントプロシージャです。


【キークリック時】
Private Sub txtTest_KeyDown(KeyCode As Integer, Shift As Integer)

【キー解放時】
Private Sub txtTest_KeyUp(KeyCode As Integer, Shift As Integer)

【キー入力時】
Private Sub txtTest_KeyPress(KeyAscii As Integer)


まず、一番下の"キー入力時"イベントプロシージャを見てみましょう。ここでは「KeyAscii」という引数が設定されています。その名称から推測できるとおり、このイベントプロシージャを使うことによって、どのASCIIコードの文字が入力されたかを判別することができます。例えば、数字のASCIIコードは、「1」から49・50・51・52・53・・・・・・というように決まっていますので、キーボードから「123456」と入力すれば、次のようなイベントプロシージャによって下図のような結果を得ることができます。

Private Sub txtTest_KeyPress(KeyAscii As Integer)

  Debug.Print KeyAscii

End Sub
実行結果のイミディエイトウィンドウ

"キー入力時"イベントは、1文字データを入力するたびに発生しますので、データ内容を1文字1文字チェックしたいような場合にこのイベントプロシージャを利用するとよいでしょう。例えば、入力規則として英字は小文字しか入力できないようにする、数字しか入力できないようにする、あるいはもっと細かく「1〜5の数字もしくは"A"という文字以外は入力できないようにする」や、「入力データの3文字目は必ず"X"でなければいけない」といったチェックも可能となるはずです。


一方、"キークリック時"および"キー解放時"イベントプロシージャの引数は、それとは異なっています。KeyAsciiに似たような感じかもしれませんが、入力されたキーを知らせてくれるのは「KeyCode」という引数です。入力されたキーが何であるかを通知するための引数であるのは同じなのに、引数名が異なっているのには理由があります。すでに説明したように、"キークリック時"イベントなどはいかなるキー入力によっても発生します。したがって、ASCIIコードで定義されていないファンクションキーや矢印キーなども通知できなければなりません。そのために別途定義された引数がこの「KeyCode」なのです。例えば、次のようなイベントプロシージャを用意し、ファンクションキー「F1」から「F5」を押してみましょう。

Private Sub txtTest_KeyDown(KeyCode As Integer, Shift As Integer)

  Debug.Print KeyCode

End Sub

その結果をイミディエイトウィンドウで確認すると次のようになります。
実行結果のイミディエイトウィンドウ

お分かりのように、「F1」キーのKeyCodeは「112」、「F2」キーのKeyCodeは「113」というように、それぞれのキーに数値が割り当てられていることが分かります。これらの数値を見ることによって、特殊キーも含めたすべてのキー操作(※注1)を検出、それによってその後の処理を分岐したり、入力キーをチェックしたりすることもできるわけです。詳細はAccessのオンラインヘルプやオブジェクトブラウザ(※注2)を参照していただきたいと思いますが、各特殊キーには定数が割り当てられています。コーディングを行う際には、この「KeyCode」引数の数値を直接扱うのではなく、それらの定数と比較して分岐処理を行うケースが多いと思います。例えば次のコードは、"キークリック時"イベントプロシージャを利用して、テキストボックスでのファンクションキー操作と矢印キー操作を処理している例です。このように、特殊キーも含めたすべてのキー入力や操作によって後処理を行いたい場合や、処理の分岐を行いたい場合には、この"キークリック時"や"キー解放時"イベントプロシージャを使うとよいでしょう。ただし、同じキーの連続入力の場合には"キー解放時"イベントは最後に1度しか発生しませんので、この点は留意しておかなければなりません。

Private Sub txtTest_KeyDown(KeyCode As Integer, Shift As Integer)

  Select Case KeyCode
    Case vbKeyF1
      MsgBox "F1キーが押されました!"
    Case vbKeyF2
      MsgBox "F2キーが押されました!"
    Case vbKeyF3
      MsgBox "F3キーが押されました!"
    Case vbKeyF4
      MsgBox "F4キーが押されました!"
    Case vbKeyF5
      MsgBox "F5キーが押されました!"
    Case vbKeyUp
      MsgBox "↑キーが押されました!"
    Case vbKeyDown
      MsgBox "↓キーが押されました!"
    Case vbKeyRight
      MsgBox "→キーが押されました!"
    Case vbKeyLeft
      MsgBox "←キーが押されました!"
  End Select
  
End Sub

※注1:「KeyCode」引数ではテンキーの数字とキーボードの数字の区別も可能です。「KeyAscii」引数ではどちらも同じ値が返されるので、それらを区別することはできません。
※注2:「VBA」ライブラリの「KeyCodeConstants」クラスのメンバから探してみてください。



もう1つ、このイベントプロシージャを使うメリット、使うべき場面としては、各キーといっしょにShift・Ctrl・Altなどの補助キーが押されているかどうかを検出したいようなときです。それには「Shift」引数を利用します。この引数は"キー入力時"イベントプロシージャにはありませんので、そのような場合にはおのずと"キークリック時"や"キー解放時"イベントプロシージャを使うことになります。例えば次の例では、Homeキーが押されたとき、単独で押されたのか、あるいはShift・Ctrl・Altのいずれかまたは複数が同時に押されているかを調べ、それに応じて処理を分岐させています。それらの補助キーが押されているかどうかの判別は、Shift引数の値とそれぞれのキーに対応した定数(acShiftMaskなど)のビットマスク(AND演算)によって行います。

Private Sub txtTest_KeyDown(KeyCode As Integer, Shift As Integer)

  If KeyCode = vbKeyHome Then
    'Homeキーが押されたとき
    If Shift = 0 Then
      MsgBox "Homeキーが単独で押されました!"
    ElseIf (Shift And acShiftMask) > 0 Then
      MsgBox "Shift + Homeキーが押されました!"
    ElseIf (Shift And acCtrlMask) > 0 Then
      If (Shift And acAltMask) > 0 Then
        MsgBox "Ctrl + Alt + Homeキーが押されました!"
      Else
        MsgBox "Ctrl + Homeキーが押されました!"
      End If
    ElseIf (Shift And acAltMask) > 0 Then
      MsgBox "Alt + Homeキーが押されました!"
    End If
  End If

End Sub

| Index | Prev | Next |

 

Copyright © T'sWare All rights reserved