除了常用的Click和DblClick事件之外,有些程序还需要对鼠标指针的位置和状态变化做出响应,因此需要使用鼠标事件MouseUp,MouseDown和MouseMove。当鼠标指针位于窗体上方时,窗体将识别鼠标事件。当鼠标指针在控件上方时,控件将识别鼠标事件。如果在对象上按下鼠标按钮不放,则该对象将继续识别所有鼠标事件,直到用户释放鼠标,即使此时指针已移开,该对象情况也是如此。
鼠标事件与Click,DblClick事件不同的是可以区分鼠标的左、右、中键与Shift,Ctrl,Alt键,并可识别和响应各种鼠标状态。鼠标事件的语法格式为:
Private Sub 对象_鼠标事件(Button As Integer, Shift As Integer, X As Single, Y As Single)
说明:
(1) Button:表示哪个鼠标键被按下或释放。用0,1,2位表示鼠标的左、右、中键,每位用1,0表示被按下或释放,三个位的二进制转换成十进制就是Button的值,如图8.15所示。例如,同时按下左、右按钮就会产生数值3(1+2)。
(2) Shift:表示当鼠标键被按下或释放时,Shift,Ctrl,Alt键的按下或释放状态。用0,1,2位表示鼠标的Shift,Ctrl,Alt键。三个位的二进制转换成十进制就是Shift值。
(3) X,Y:表示鼠标指针的坐标位置。如果鼠标指针在窗体或图片框中,用该对象内部的坐标系,其他控件则用控件对象所在容器的坐标系。

图8.15 Button键
1.MouseDown和MouseUp事件
MouseDown和MouseUP事件是当鼠标按下或释放时触发,通常用来在运行时调整控件在窗体上的位置,或实现某些图形效果。
将MouseDown事件与Move方法结合起来使用,就可以将命令按钮移动到窗体的不同位置。鼠标指针的位置决定按钮的新位置:在单击窗体的任意位置时,控件将移动到光标位置。过程From_MouseDown将执行此操作:
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Command1.Move X, Y
End Sub
使用MouseDown事件和Line方法在先前的绘制位置与鼠标指针的新位置之间画一条直线,则可用下面的语句实现:
Line -(X, Y)
如图8.16所示,第一条直线开始于缺省起点,也就是左上角。无论何时,只要按下鼠标按钮,应用程序就会绘制一条从先前直线终点到鼠标目前位置的直线。


图8.16 使用MouseDown事件绘制连接的直线 图8.17 结合MouseUp和MouseDown事件画直线
释放鼠标按钮时,MouseUp事件将发生。例如,在窗体中画线:在鼠标按钮按下的位置出现一个端点,在鼠标按钮被释放的位置出现另一个端点:
Dim X1, Y1
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
X1 = X: Y1 = Y
End Sub
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Line (X1, Y1)-(X, Y)
End Sub
当MouseDown事件发生时,鼠标指针的位置被保存到X1和Y1中。当MouseUp事件发生时,则以X1,Y1为起点坐标,当前鼠标指针位置X,Y为终点,绘制一条直线,如图8.17所示。
2.MouseMove事件
当鼠标指针在屏幕上移动时就会发生MouseMove事件,窗体和控件均能识别该事件。使用图形方法在MousrMove过程的效果与在MouseDown过程中的效果截然不同,例如前面在MouseDown事件中使用Line方法是绘制连接的直线,而将Line方法放入在MouseMove过程中则绘制曲线,如图8.18所示。


图8.18 使用MouseMove事件绘制曲线 图8.19 MouseMove发生频率的演示
当移动鼠标时,MouseMove事件不断发生,但并不是对鼠标经过的每个象素都会触发。例如,在Form_MouseMove事件过程中加入Circle方法:
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Line -(X, Y)
Circle (X, Y), 50
End Sub
如图8.19所示,鼠标指针移动得越快,在两点之间触发的MouseMove事件越少,众多圆圈挤在一起表明鼠标在此位置移动缓慢。
由于应用程序能接二连三地触发大量的MouseMove事件,因此MouseMove事件不应去做需要大量时间的工作。
Button参数对于MouseMove事件与MouseDown,MouseUp事件不同,MouseMove事件的Button值表示所有按键的状态,而MouseDown和MouseUp事件的Button的值无法检测是否同时按下两个以上的按键。
【例8.5】 制作一个简单的画图程序,使其具有绘画、擦除功能。
在窗体中添加一个图片框Picture1,两个按钮(数组形式),如图8.20所示。当单击绘画按钮后,在Picture1中按下鼠标左键后拖动就可以随意地画线或写字,释放鼠标后就停止画线。单击擦除按钮可通过画一个白色的圆点将图像擦除。

图8.20 画图
程序代码如下:
Option Explicit
Dim MouseState As Integer
Dim Isdraw As Boolean
Private Sub Command1_Click(Index As Integer)
Select Case Index
Case 0 '单击绘画按钮
MouseState = 1
Case 1 '单击擦除按钮
MouseState = 2
End Select
End Sub
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
If Button = 1 And MouseState = 2 Then
Picture1.FillStyle = 0
Picture1.FillColor = RGB(255, 255, 255)
Picture1.ForeColor = RGB(255, 255, 255)
Picture1.Circle (X, Y), 50
ElseIf Button = 1 And MouseState = 1 Then
Isdraw = True
Picture1.CurrentX = X
Picture1.CurrentY = Y
End If
Picture1.AutoRedraw = True
End Sub
Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Picture1.ForeColor = RGB(0, 0, 0)
If Isdraw And MouseState = 1 Then
Picture1.Line -(X, Y)
End If
End Sub
Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
If Button = 1 And MouseState = 1 Then Isdraw = False
End Sub
同时使用了MouseMove,MouseDown和MouseUP事件,当鼠标按下时触发MouseDown事件,当鼠标移动时触发MouseMove事件,线的起点为上次的终点,当鼠标释放时触发MouseUp事件,使变量Isdraw为False就不能画线。