Итак, на форму помещается некоторый элемент управления, скажем, Label или CommandButton. Часто требуется что бы он как-то реагировал на наведение курсора на себя любимого. Скажем, менял цвет или иконку на себе, тем самым сигнализируя пользователю что это именно работающая кнопка а не что-то там еще.
С наведением курсора просто - при этом генерируется событие MouseMove его мы и поймаем. А как быть с моментом ухода(leave) курсора с нашего контрола? События MouseLeave в VB как известно нету.
Для решения этого вопроса мы и рассмотрим пару методов в порядке убывания их кривости(на мой взгляд):
1. Ловить событие MouseMove на контейнере.
Тут все просто, если кнопочка размещена скажем на форме, то в тот момент когда курсором водят по форме, очевидно, им уже не водят по самой кнопке. Поэтому, достаточно написать простой код и мигающая кнопка готова!
- Код: Выделить всё
Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.FontItalic = True
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.FontItalic = False
End Sub
Минусы этого кода перевешивают все плюсы простоты. Достаточно перенести кнопку в какой-нибудь угол и наша метода тут же перестает работать, не говоря уже о многих других минусах. Именно поэтому в ряду кривости этот метод занимает почетное первое место.
2. Сабклассинг события WM_MOUSELEAVE.
Вот так оказия, хоть в VB6 события MouseLeave и нету, тем не менее в windows есть сообщение WM_MOUSELEAVE. Совершенно очевидно, что если это окно засабклассить, то можно ловить это сообщение(правда на него еще надо подписаться с помощью TrackMouseEvent, но это уже другая история) и легко сделать такую же "мигающую" кнопку. Я не буду приводить код этого способа, сабклассингу посвящено много статей. Могу лишь пожелать людям, которые изберут этот метод удачи при отладке своих приложений. Ибо она им пригодится.
3. Таймер и сравнение rect'ов.
Тут то же все просто. В событии MouseMove мы запускаем некоторый таймер, который с регулярностью в 100 мс проверяет, не ушел ли курсор за пределы прямоугольника нашего окна. Если ушел - пора гасить свечи. Код то же простой:
- Код: Выделить всё
Option Explicit
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Not Timer1.Enabled Then
Timer1.Enabled = True
Command1.FontItalic = True
End If
End Sub
Private Sub Timer1_Timer()
Dim rc As RECT, pt As POINTAPI
GetWindowRect Command1.hwnd, rc
GetCursorPos pt
If pt.X < rc.Left Or pt.X > rc.Right Or pt.Y < rc.Top Or pt.Y > rc.Bottom Then
Timer1.Enabled = False
Command1.FontItalic = False
End If
End Sub
Плюсы этого способа очевидны: он работает где-бы не располагался наш контрол(на любом контейнере и в любой его области). Минусов у этого способа на самом деле нету, если не считать таймера. Он видите ли некоторым не нравится. Ну, для них есть еще один метод.
4. Захват мыши.
Захват(Capture) мыши заключается в том, что windows будет посылать события MouseMove нашему окну даже тогда, когда курсор покинет его приделы (иными словами до тех пор, пока мы ее не отпустим). Код еще короче, чем в прошлый раз:
- Код: Выделить всё
Private Declare Function SetCapture Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Static bCaptured As Boolean
If bCaptured Then
If X > Command1.Width Or Y > Command1.Height Or X < 0 Or Y < 0 Then
ReleaseCapture
bCaptured = False
Command1.FontItalic = False
End If
Else
Command1.FontItalic = True
bCaptured = True
SetCapture Command1.hwnd
End If
End Sub
На последок отмечу, что последний способ - мой любимый, хотя бы потому, что он краток и удобен в использовании и для него не надо еще одного контрола на форме.
Ну и конечно же, всех с Новым Годом!