Visual Basic 初級講座 |
Visual Basic 中学校 > 初級講座 >
第21回 マウス・キーボードからの入力
マウス・キーボードから入力をVBで受け取る方法を説明します。右クリックや、マウスホイール、それに[Alt] + [R]のようなキーボード入力が登場します。
この回の要約 ・マウス系のイベントをつかうとマウスの動作を捕捉することができる。 ・キーボード系のイベントをつかうとキーボード入力を捕捉することができる。 ・右クリックはMouseUpイベントで判定する。 ・MouseWheelイベントの使用例 ・マウスが来たときにラベルを光らせるにはMouseEnterイベントを使う。 ・特定のキーの入力をキャンセルにはKeyPressイベントを使う。 ・押されたキーの組み合わせを判定するにはKeyDownイベントやKeyUpイベントを使う。 |
ユーザーがアプリケーションを操作するときはマウスとキーボードを使用します。もちろん、それ以外のケースも考えられますがよほど特殊でなければマウスとキーボードのことだけを考えていれば問題ありません。
マウスとキーボードはアプリケーションを操作する主要な入力装置のため、VBでもこの2つからの入力情報の取得・制御するためにたくさんのイベントが用意されています。
今回はまずマウスから入力情報を取得する方法を説明し、後半はキーボードからの入力情報を取得し、ある程度の制御を行う方法も説明します。どちらも特にVBが配慮しているケースですのでとてもスマートにプログラムの中で利用することができます。
マウスからの入力は、基本的にはクリック、ダブルクリック、右クリック、ホイール、カーソルの移動の5種類です。ドラッグ&ドロップはこれらを組み合わせた入力方法でやや複雑です。ドラッグ&ドロップについては次回解説します。
VBではこれらの入力が行われるとイベントが発生します。マウスからの入力により発生するイベントは次の通りです。この表にはドラッグ&ドロップを除いてマウスからの入力により発生するすべてのイベントが記載されています。
イベント | 読み方 | 第2引数の型 | 概要 |
Click | クリック | EventArgs | マウスを左クリックしたときに発生します。その他の場合でも発生する場合があります。 |
DoubleClick | ダブルクリック | EventArgs | マウスを左ダブルクリックしたときに発生します。 |
MouseClick | マウスクリック | MouseEventArgs | VB2005以降。マウスのどれかのボタンをクリックしたときに発生します。 |
MouseDown | マウスダウン | MouseEventArgs | マウスのボタンを押したときに発生します。左右中央どのボタンでも発生します。 |
MouseEnter | マウスエンター | EventArgs | マウスカーソルがコントロールの上に移動してきたときに発生します。 |
MouseHover | マウスホバー | EventArgs | マウスカーソルがコントロールの上で移動を停止したときに発生します。 |
MouseLeave | マウスリーヴ | EventArgs | マウスカーソルがコントロールの上から外へ離れていったときに発生します。 |
MouseMove | マウスムーブ | MouseEventArgs | マウスカーソルがコントロールの上を移動すると発生します。 |
MouseUp | マウスアップ | MouseEventArgs | 既に押されているマウスのボタンを離したときに発生します。左右中央どのボタンでも発生します。 |
MouseWheel | マウスホイール | MouseEventArgs | コントロールにフォーカスがあるときにマウスホイールを回転させるとき発生します。 |
■表1:マウスイベント
この表を見るとわかるのですが、「右クリック」で発生するイベントはありません。右クリックを検知したいときはMouseUpを使 って次のようにプログラムします。
Private
Sub Form1_MouseUp(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.MouseEventArgs) Handles
MyBase.MouseUp If e.Button = MouseButtons.Right Then MsgBox("右クリックしました!") End If End Sub |
■リスト1:右クリックの判定
MouseUpイベントの第2引数を使うとイベントが発生したときのマウスの状態がわかりますからこのようなプログラムが可能です。
VB2005ならば同じことをMouseClickイベントでも行えます。
このプログラムでは、MouseEventArgs(読み方:MouseEventArgs = マウスイベントオーグス)のButtonプロパティ(読み方:Button = ボタン)が、MouseButtons.Right(読み方:MouseButtons = マウスボタンズ, Right = ライト)であれば右クリックであると判断しています。
実際にはMouseUpイベントは、既に押されているマウスボタンが離されたときに発生するので、このプログラムの意味は「マウスの右ボタンが離されたら…」という条件になっているわけですが、ボタンを離すと言うことはほとんどクリックと同じ意味になるわけですから右クリックの判定としては問題ありません。もちろん、ボタンが押されたときにMouseDownイベントを利用して右クリックを判断することもできますが、イベントが発生するタイミングがMouseUpとMouseDownではことなります。MouseUpで判断する方が自然な操作感があります。
上の表を見るとわかりますが、この他にもMouseMove, MouseWheelでも同じMouseEventArgs型の第2引数を受け取りますので同様の手法でマウスの状態を取得することができます。ただし、イベントの発生のタイミングが異なるのでこれらを右クリックの判定に使うことはできません。
以下では、先の紹介したマウスイベントを実際の2つの使用例とともに紹介します。
まず、マウスホイールの回転に合わせて視覚的に量が増減するプログラムを作ってみます。見かけで実感できるちょっと楽しいプログラムですので是非実際に作ってみてください。
■画像1:このようにMouseWheelの操作を量に置き換えて視覚的に表現する。
まずフォームにピクチャーボックス(PictureBox)を1つ配置してください。このピクチャーボックスは縦に長く配置します。
そしてピクチャーボックスのプロパティを次のように設定してください。
プロパティ | 値 | 説明 |
BackColor | Black | 背景色を黒にします。 |
BorderStyle | Fixed3D | へこませます。 |
■表2
プログラムは次のようになります。
Dim MouseValue As Integer |
Private
Sub Form1_Activated(ByVal
sender As Object,
ByVal e As
System.EventArgs) Handles
MyBase.Activated PictureBox1.Select() End Sub |
Private
Sub PictureBox1_MouseWheel(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.MouseEventArgs) Handles
PictureBox1.MouseWheel '▼ホイールの回転量を元に現在の値を加算する。 MouseValue += e.Delta If
MouseValue > 1000 Then
'値の最高値を1000に限定する。 '▼PictureBox1のPaintイベントを呼び出す。 PictureBox1.Invalidate() End Sub |
Private
Sub PictureBox1_Paint(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.PaintEventArgs) Handles
PictureBox1.Paint Dim ThisRect As Rectangle '▼描画する四角形の座標を計算する。 ThisRect.Width =
PictureBox1.Width
'四角形の幅はPictureBox1の幅と同じ。 '▼描画実行。赤い四角形を描画する。 e.Graphics.FillRectangle(Brushes.Red, ThisRect) End Sub |
■リスト2:MouseWheelの効果を視覚的に表示する
このプログラムはPaintイベント中の座標計算がやや複雑ですが、肝心のMouseWheelイベントは難しくありません。MouseWheelイベントが発生したときにMouseEventArgsのDeltaプロパティ(読み方:Delta = デルタ)でホイールの回転量を取得して、変数MouseValueに記録しておきます。そして、PaintイベントでMouseValueの値に応じて赤い四角形を描画するわけです。
ちょっと注意が必要なのはMouseWheelイベントはフォーカスのあるコントロールが受け取るということです。そのためこのプログラムではPictureBox1に強制的にフォーカスを与えるためにフォームのActivatedイベント(読み方:Activated = アクティベイテッド)でPictureBox1のSelectメソッドを呼び出しています。Activatedイベントはフォームがアクティブになった直後に発生します。(この場合の「アクティブ」とはユーザーから入力を受け取れるように準備が整った状態を指します。)
途中に出てくる演算子「 += 」は加算を意味しています。MouseValue += e.Delta とは、「現在のMouseValueに値に e.Delta を加えなさい」という意味です。ホイールを下向きに回転させた場合e.Deltaの値はマイナスになるので、実際には加算だけではなく減算も行われます。
この部分は += 演算子を使わないで、 MouseValue = MouseValue + e.Delta と書くこともできます。
PictureBoxのInvalidateメソッド(読み方:Invalidate = インバリデイト)は今回はじめて登場しましたが、要はPaintイベントを呼び出しているだけです。PatinイベントはWindowsが描画必要と判断した場合には自動で呼び出されますが、そうでない限りはInvalidateメソッド等を使って自分で呼び出す必要があります。
次に、マウスが来ると光るラベルを作ります。今度の例はイベントを素直に使うだけの簡単なものです。
まず、フォームにラベルを1つ貼り付けて次の通りプロパティを設定してください。
プロパティ | 値 | 説明 |
BackColor | Black | 背景色を黒にします。 |
BorderStyle | Fixed3D | へこませます。 |
Font | サイズ16, 太字 | 文字を大きくします。 |
ForeColor | Chocolate | 文字の色をチョコレート色にします。 |
Text | Mouse Test | |
TextAlign | MiddleCenter | 文字をラベルの中央に表示します。 |
■表3
プログラムは次の通りです。
Private
Sub Label1_MouseEnter(ByVal
sender As Object,
ByVal e As
System.EventArgs) Handles Label1.MouseEnter Label1.BackColor = Color.LawnGreen End Sub |
Private
Sub Label1_MouseLeave(ByVal
sender As Object,
ByVal e As
System.EventArgs) Handles Label1.MouseLeave
Label1.BackColor = Color.Black End Sub |
Private Sub
Label1_MouseHover(ByVal sender
As Object,
ByVal e As
System.EventArgs) Handles Label1.MouseHover Label1.Text = "●HOVER●" End Sub |
■リスト3
このプログラムは単純なので解説の必要はほとんどありません。実行するとどうなるかは実際に試してみてください。
さて、マウスイベントの最後にClickイベントについて簡単に注意を書いておきます。
Clickイベントはクリックしなくても発生する場合があります。たとえば、チェックボックスやラジオボタンにフォーカスがあるときに[スペース]キーを押すとクリックイベントが発生します。 また、ボタンにフォーカスがあるときに[ENTER]キーを押してもクリックイベントが発生します。他にもマウスのクリック以外でClickイベントが発生する場合があるようです。
なぜこのような仕様なのかはわかりません。VB6時代からの伝統でしょうか?
とはいっても普通に使っている限りこの仕様で特に困ることはありません。むしろ便利です。どうしても、マウスでクリックしたときだけに反応したい場合はMouseClickイベントを使います。ただし、MouseClickイベントはVB2005以降でないと使えません。
キーボードからの入力のために使うイベントは3つしかありません。マウスと違って「移動」という操作がないからです。キーボードからの入力では「どのキーが押されたか」という情報が最も重要です。また、[Ctrl] + [C] や [Alt] + [Enter]などのように押されたキーの組み合わせが重要な場合もあります。
イベント | 読み方 | 第2引数の型 | 概要 |
KeyDown | キーダウン | KeyEventArgs | キーを押したときに発生します。 |
KeyPress | キープレス | KeyPressEventArgs | キーボードから文字キーを入力したときに発生します。 |
KeyUp | キーアップ | KeyEventArgs | 既に押されているキーを離したときに発生します。 |
■表4:キーボードイベント
KeyDownイベントとKeyUpイベントはどのキーが押されたときでも発生するのですが、KeyPressイベントは「文字キー」が押されたときにしか発生しません。この辺りの事情が初心者にはわかりにくくなっています。
「文字キー」というのは今、私が便宜のために勝手に使っている言葉ですが、要するに文字のキーです。たとえば、[A], [B], [C]です。
一方、文字のキーではない[F1], [SHIFT], [DELETE]などではKeyPressイベントは発生しません。
ここまでは単純に切り分けられるので理解もしやすいのですが、複雑なのはここからです。[ESC], [スペース], [ENTER], [BackSpace]は例外的にKeyPressイベントが発生します。
[スペース]や[ENTER]はまだしも、[BackSpace]ではKeyPressイベントが発生するのに、[DELETE]ではKeyPressイベントが発生しないなどはっきりいって知らなきゃわかりません。きっと昔からのパソコン・環境の仕様との関連で現在もこのような仕様になっているのでしょう。
KeyPressイベントを使って押されたキーを判断するにはKeyPressEventArgs型(読み方:KeyPressEventArgs = キープレスイベントオーグス)の第2引数のKeyCharプロパティ(読み方:KeyChar = キーキャラ)を使います。
Private
Sub TextBox1_KeyPress(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles
TextBox1.KeyPress ListBox1.Items.Add(e.KeyChar) End Sub |
■リスト4:入力された文字をリストボックスにも表示する
この例では、入力された文字をリストボックスにも追加していきます。KeyPressイベントの動作を実験するのにはちょうどよいプログラムです。たとえば、IMEで漢字変換したときにKeyPressイベントがどのように反応するかは知っておいて損はありません。
結論を言うとIMEで漢字変換などの日本語編集中はキーボード関連のイベントは発生しません。この場合は変換を確定した瞬間にイベントが発生します。そのときにはKeyCharプロパティは押されたキーボードのキーの文字ではなく、変換後の文字がセットされています。
なお、KeyPressEventArgsのHandledプロパティ(読み方:Handled = ハンドルド)にTrueをセットすることによりキーが処理済であることを.NET Frameworkに通知することができます。この通知がなされると本来の自動的に行われる処理が行われなくなります。
たとえば、次のプログラムでは入力した文字がリストボックスには表示されますが、肝心のテキストボックスには表示されなくなります。
Private
Sub TextBox1_KeyPress(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles
TextBox1.KeyPress ListBox1.Items.Add(e.KeyChar) e.Handled = True End Sub |
■リスト5
でも、VB.NET2002およびVB.NET2003ではIMEによる日本語入力はテキストボックスにも表示されます。多分、IMEによる日本語入力は .NET Framework 1.1によるキーボード処理とは違う経路をたどっているのでしょう。もし、プログラムで日本語入力まで詳細に制御しようとするならば相当の苦労を強いられることでしょう。
VB2005では、リスト5のプログラムで日本語入力もきちんと処理することができます。
Handledプロパティを使うと特定の文字の入力を禁止することもできます。
次の例はテキストボックスに "P" を入力できなくします。"p"は入力できます。
Private
Sub TextBox1_KeyPress(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles
TextBox1.KeyPress
If e.KeyChar = "P"
Then |
■リスト6:"P"の入力をキャンセルする。
でもやはりVB.NET2002およびVB.NET2003ではIMEの日本語入力を使うと半角のPを入力できてしまいます…。テキストボックスのIMEModeプロパティ(読み方:IMEMode = アイエムイーモード)をDisable(読み方:Disable = ディスエイブル)にするとIMEが使用不可になりますのでこの問題を回避できますが、すべての全角文字が入力できなくなるというデメリットもあります。
VB2005では、IMEの日本語入力使ったとしても"P"の入力を完全にキャンセルすることができます。
ただし、どのバージョンのVBであってもKeyPressイベントでは「貼り付け」を防げない点には注意してください。つまり、メモ帳か何かから"P"と言う字をコピーして、このテキストボックスに貼り付けることはできます。
まぁVB.NET2003以前のバージョンでは文字の入力自体を細かく制御することはできるだけ避けた方が良さそうです。それでも、どうしても"P"が許せない場合はValidatingイベント(読み方:Validating = バリデイティング)を使って入力のチェックを行うことになります。このイベントはKeyPressイベントと違って素直に動作してくれて使いやすいのでお勧めです。このイベントについては次々回で説明する予定です。
最後に残されたKeyDownとKeyUpについて説明します。この2つはKeyPressではドラップできない[F1]、 [Shift]などのキーの検出に使います。また、KeyPressイベントはキーを押したときに1回だけ発生するのに対して、KeyDownイベントとKeyUpイベントを組み合わせるとキーが現在押しっぱなしになっているかどうかを判断することもできます。
KeyDownイベントもKeyUpイベントも文字に着目しているKeyPressイベントとは異なり、キーボードのキーに着目します。たとえば、この2つのイベントでは"A"も"a"も同じ意味になります。
この2つのイベントの第2引数のKeyEventArgs型は以前のバージョンのVBにくらべて大変親切になっているのですぐに使い方がわかります。代表的なプロパティをまとめると次の通りです。
プロパティ | 読み方 | 説明 |
Alt | オルト | イベントが発生したときに[Alt]キーが押されていたかを示します。 |
Control | コントロール | イベントが発生したときに[Ctl]キーが押されていたかを示します。 |
KeyCode | キーコード | 押されたキーのコードを示します。 |
Shift | シフト | イベントが発生したときに「Shift]キーが押されていたかを示します。 |
■表5
これらを使うと簡単に押されたキーの情報を取得します。
次のプログラムでは[Alt] + [R] を押すとフォームの背景を赤にします。 [Shift] + [Alt] + [R]を押すと元の色に戻します。
Private
Sub Form1_Load(ByVal
sender As System.Object,
ByVal e As System.EventArgs)
Handles MyBase.Load
'フォームでキーボードイベントを認識するにはKeyPreview = True にする。 |
Private Sub
Form1_KeyUp(ByVal sender
As Object, ByVal
e As System.Windows.Forms.KeyEventArgs)
Handles MyBase.KeyUp
If
e.KeyCode = Keys.R Then |
■リスト7
この例からもわかるようにKeyCodeプロパティを使って押されたキーを判定するにはKeys列挙体(読み方:Keys = キーズ)を使用します。これはVBで色を表すときにColor.RedやColor.Blackなどと書くことができるのと同様に手軽にKeys.RやKeys.Enterなどと書くことができます。文字以外の代表的な制御キーがKeys列挙体でどのように表現されるかを参考のため表にしておきます。
キーボード | Keys列挙体の値 |
[ESC] | Escape |
[F1], [F2], ... | F1, F2, ... |
[Enter] | Enter |
[←], [↑], [→], [↓] | Left, Up, Down, Right |
キーボードの[1], [2], [3], ... | D1, D2, D3, ... |
テンキーの[1], [2], [3], ... | NumPad1, NumPad2, NumPad2, ... |
■表6
このほかにもさまざまな制御キーを判定することができます。詳細はMSDNライブラリをご覧下さい。
中にも見たことも聞いたこともない外国用の制御キーもあります。