VB-Tec.de Visual Basic - Technik, FAQ, Tricks, BeispieleHome / System / Maus u. Kbd. / Over Feststellen, ob der Mauszeiger ein Control verläßt |
Bei grafisch anspruchvollen Benutzer-Oberflächen hat man oft das Problem zuverlässig bestimmen zu müssen, ob der Mauscursor ein Control gerade betreten oder - was weit schwieriger festzustellen ist - gerade verlassen hat. Dies wird z.B. bei der Reproduktion des beliebten Hover-Effekts (ein optischer Feedback) benötigt oder bei der Aktualisierung der Statuszeile (als Kontext-sensitive ToolTips-Ergänzung bzw. Kurz-Hilfe).
Als ersten Lösungs-Ansatz wird man sicher auf das MouseMove-Ereignis zurückgreifen wollen, welches immer dann ausgelöst wird, wenn die Maus über ein Control fährt. Doch wie soll dann festgestellt werden, ob und wann die Maus das Control verläßt? Man könnte zwar auf das MouseMove-Ereignis des Formulars zurückgreifen, aber leider arbeitet diese Methode nicht zuverlässig: Wird z.B. der Mauszeiger schnell von einem Control in ein anderes gezogen (oder gar ganz aus dem Formular hinaus), so bekommt das Formular überhaupt kein Ereignis mit.
Zum Glück stellt die Windows-API Hilfsmittel zur Verfügung, um ein Control zu "verfolgen" (engl. "to capture"). Damit werden alle MouseMove-Ereignisse immer an dieses eine Control gesendet, egal wo die Maus gerade steht.
Mit der unten vorgestellten MouseOverState-Funktion wird für ein gegebenes Control ctl überprüft, ob die Maus gerade darüber "schwebt". Falls nein, so gibt die Funktion vbLeave zurück. Wird das Control bereits verfolgt, so gibt die Funktion vbOver zurück, ansonsten wird die Verfolgung iniziiert und ein vbEnter zurückgegeben (s.a. Online-Hilfe zum DragOver-Ereignis).
Im diesem Beispiel wechselt die Beschriftung des CommandButtons cmdTest folgendermaßen: Fährt die Maus in die Schaltfläche rein, so erscheint "in"; Wird die Maus innerhalb des Buttons bewegt, so ertönt (zu Testzwecken) ein akustisches Signal; Verläßt der Mauscursor die Schaltfläche, so erscheint "out".
Private Sub cmdTest_MouseMove(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
Select Case MouseOverState(cmdTest)
Case vbEnter
cmdTest.Caption = "in"
Case vbOver
Beep 'Test
Case vbLeave
cmdTest.Caption = "out"
End Select
End Sub
Im Deklarationsteil eines Moduls oder Formulars müssen folgende API-Routinen zur Verfügung gestellt werden:
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" ( _
lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" ( _
ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetCapture Lib "user32" ( _
) As Long
Private Declare Function SetCapture Lib "user32" ( _
ByVal hWnd As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" ( _
) As Long
Die eigentliche Funktion sieht dann folgendermaßen aus:
Public Function MouseOverState( _
ByRef ctl As Control _
) As DragOverConstants
'Deklarationen:
Dim Point As POINTAPI
Dim Window As Long
'hWnd des Controls unter der Maus bestimmen:
GetCursorPos Point
Window = WindowFromPoint(Point.X, Point.Y)
'Handles vergleichen:
If ctl.hWnd = Window Then
'Feststellen, ob Control gewechselt hat:
If GetCapture() <> Window Then
'Verfolgung starten:
SetCapture Window
MouseOverState = vbEnter
Else
'Verfolgung fortsetzen:
MouseOverState = vbOver
End If
Else
'Verfolgung stoppen:
ReleaseCapture
MouseOverState = vbLeave
End If 'ctl.hWnd = Window
End Function
© Jost Schwider, 31.03.2001-31.03.2001 - http://vb-tec.de/mausover.htm