マウスイベントの処理

使いやすいソフトを作るには,マウスのクリックやドラッグ・ドロップなどに応じたプログラムを書く必要が出てきます。

ここでは,フォームの

というイベントの処理を説明します。
Form上のPictureBoxに対しても全く同様な処理ができます。


Click,MouseDown, MouseUp

クリックとは,マウスボタンが押され,それが離されるたときに発生するイベントです。マウスボタンが押されたことも1つのイベントですし,ボタンが離されたことも1つのイベントになります。
そのため,クリックというイベントが発生するときには,必ず次の順でイベントが発生します。

順序 イベント イベントプロシージャ
1. MouseDown (マウスボタンが押された) → Sub Form_MouseDown
2. MouseUp (ボタンが開放された) → Sub Form_MouseUp
3. Click → Sub Form_Click

練習 上記のことを確認するプログラムを書きなさい。
   (ヒント) 例えば,Sub Form_MouseDown では,Print "MouseDown" を実行させる。

例1 フォームをクリックたびに背景色を白から黒,黒から白に変更する。

Private Sub Form_Click()
    If BackColor = vbWhite Then
        BackColor = vbBlack
    Else
        BackColor = vbWhite
    End If
End Sub

ここでわかるように,Sub Form_Click には,受け渡されるパラメータがありません。
そのため,左右どちらのボタンがクリックされたのかもわかりません。

また,クリックされた位置を知りたい場合は,MouseDownの位置とMouseUpの位置が異なっている可能性があるので,結局そのいずれか(通常MouseUp)を使うことになります。

例2 クリックした位置に小円が描かれるようにしなさい。

Option Explicit

Private Sub Form_Load()
    ScaleMode = vbPixels    'フォームの座標は画素単位
End Sub

Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Circle (X, Y), 2
End Sub

ここでは,Form_MouseUpに渡されるパラメータのうち,マウスポインタの位置 X, Y だけを使っています。この座標は,フォームに設定されている座標系での値です。

他のパラメータの意味は以下の通りです。

Button 1=左ボタン, 2=右ボタン, 4=中(ホイール)ボタン
vbLeftButton, vbRightButton, vbMiddleButton などの定数が用意されています。
Shift 0=キーは押されていない
1=Shiftキー, 2=Ctrlキー, 4=Altキー
vbShiftMask, vbCtrlMask, vbAltMask などの定数が用意されています。
例えば,ShiftとCtrlが同時に押されておれば 3 になる。

これらを使えば,どのボタンが使われたか,そのときShiftキーが押されていたか否かなどを調べることができます。

例3 例2で,右クリックの場合は画面を消去するようにしなさい。

Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbRightButton Then
        Cls
    Else
        Circle (X, Y), 2
    End If
End Sub

Shiftキーが押されているときは,Shiftの値が1, 3, 5, 7 のいずれかになります。
他のキーには関係なくとにかくShiftが押されているか否かを調べたいときは,
    If Shift And vbShiftMask Then
という構文を使えば簡単でわかりやすいでしょう。(Andはビット演算をします。)

例4 例3で,Ctrlが押されておれば赤い円を描くようにしなさい。

Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbRightButton Then
        Cls
    Else
        If Shift And vbCtrlMask Then
            Circle (X, Y), 2, vbRed
        Else
            Circle (X, Y), 2
        End If
    End If
End Sub

MouseMove

マウスポインタが動いたときには,Sub Form_MouseMove が呼び出されます。パラメータはMouseUpと同じです。

例5 Shiftキーを押しながらマウスを動かすとその軌跡に沿って点が描かれるようにしなさい。

Option Explicit

Private Sub Form_Load()
    ScaleMode = vbPixels    'フォームの座標は画素単位
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Shift And vbShiftMask Then
        PSet (X, Y)
    End If
End Sub

例6 例5で,点ではなく線で軌跡を描くようにしなさい。

PsetではなくLineを使うためには,1つ前の点の位置を記憶しておかねばなりません。
これを記憶する変数XX, YYは,イベントプロシージャが終了しても残っていなくてはならないので,プロシージャの外で宣言しておく必要があります。

とりあえず,次のようにしてみましょう。

Option Explicit
Dim XX As Single, YY As Single

Private Sub Form_Load()
    ScaleMode = vbPixels    'フォームの座標は画素単位
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Shift And vbShiftMask Then
        Line (XX, YY)-(X, Y)
        XX = X: YY = Y
    End If
End Sub

このままでは,書き始めがうまくいきません。最初は線を引かないようにするため,最初であることを示すフラグ変数Firstを導入します。
最初は,First = True にしておき,このときは線を描かず位置だけを記憶します。一度位置を記憶したら First = False になるようにしておき,First = False のときのみ線を引くようにします。
最後も判定しておく必要があります。ここでは,Shiftキーが押されていなければ,First = True とすることにします。こうしておけば,次にShiftを押して軌跡を描くときもうまくいきます。

Option Explicit
Dim XX As Single, YY As Single
Dim First As Boolean

Private Sub Form_Load()
    ScaleMode = vbPixels    'フォームの座標は画素単位
    First = True
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Shift And vbShiftMask Then
        If Not First Then Line (XX, YY)-(X, Y)
        XX = X: YY = Y
        First = False
    Else
        First = True
    End If
End Sub