按照我的理解,给你一个简单的例子: Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Command1.Caption = "鼠标在按钮上" End Sub Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Command1.Caption = "鼠标不在按钮上" End Sub
'捕捉 MouseExit 事件(源程序) Private Declare Function SetCapture Lib "user32" (ByVal hWnd As Long) As Long Private Declare Function ReleaseCapture Lib "user32" () As LongPrivate Sub Cmd1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) With Cmd1
If (X < 0) Or (Y < 0) Or (X > .Width) Or (Y > .Height) Then
ReleaseCapture ' 放入鼠标离开的代码 .Caption = "Out"
Else
SetCapture .hWnd ' 放入鼠标进入的代码 .Caption = "in"
End If
End With
End Sub
这个方法已经用过了,我同一个Form有很多个 image ,用Form的MOVE 事情,太慢了。。 如果有二十个控件,, Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Command1.Caption = "鼠标不在按钮上" Command2.Caption = "鼠标不在按钮上" Command3.Caption = "鼠标不在按钮上" ... Command20.Caption = "鼠标不在按钮上" End Sub 这样效率有点低。
换image为picbox,如果不能换,只能靠timer控件来实时监测
不可以换成Picbox.. 用timer如何来监测呢。。
只能写个大概: type pointapi x as long y as long end type引用windowfrompoint和getcursorpos API private sub timer1_timer() dim hcursorwnd as long,point as pointapi getcursorpos point hcursorwnd=windowfrompoint(point.x,point.y) if point.x and point.y 在commandbutton上 then ... else ... end if end sub
Private Declare Function SetCapture Lib "user32" (ByVal hWnd As Long) As Long Private Declare Function ReleaseCapture Lib "user32" () As LongDim obj As ObjectPrivate Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) If obj Is Nothing Then Exit Sub End If If X < obj.Left Or X > obj.Left + obj.Width Or Y < obj.Top Or Y > obj.Top + obj.Height Then ReleaseCapture obj.Caption = "离开了" Set obj = Nothing End If End SubPrivate Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) SetCapture Me.hWnd Set obj = Command1 Command1.Caption = "进来了" End Sub Private Sub Frame1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) SetCapture Me.hWnd Set obj = Frame1 Frame1.Caption = "进来了" End SubPrivate Sub Label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) SetCapture Me.hWnd Set obj = Label1 Label1.Caption = "进来了" End SubPrivate Sub Label2_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) SetCapture Me.hWnd Set obj = Label2 Label2.Caption = "进来了" End Sub Private Sub Label3_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) SetCapture Me.hWnd Set obj = Label3 Label3.Caption = "进来了" End Sub
重载控件的消息循环(子类化),在WM_MOUSEMOVE消息,调用TrackMouseEvent函数,其中TRACKMOUSEEVENTTYPE结构填充为: With tTrackMouse .cbSize = Len(tTrackMouse) .dwFlags = TME_LEAVE .hwndTrack = 控件.hwnd End With这样,当鼠标离开该控件,系统会给其发WM_MOUSELEAVE消息,这样就可以得知了。 注意,需要设置一个标志,避免在WM_MOUSEMOVE里多次调用TrackMouseEvent。
路过.IMAGE是轻量控件.......无句柄的.我提供个思路,楼主看看如何吧:同一时间鼠标只能在一个控件上产生MOVE消息.那么,你窗体里定义一个变量,其值为唯一标志每个控件的内容,比如控件NAME & INDEX.然后写一个函数,在每个控件的MOUSEMOVE事件里调用即可:private ControlFlag as stringprivate sub GetMouse(byval theFlag as string) if theflag<>controlflag then '这里就可以确定上次鼠标所在控件,即鼠标"离开"了哪个控件 debug.print "离开了:" & controlflag , "进入了:" & theflag end if end subprivate sub Image1_MouseMove(xxxxxxxxxxxxxxxxxx) call getmouse("Image1") '每个控件的MOUSEMOVE事件里加这一句即可 '其它内容 end sub 这样子结构好些.话又说回来,最多是编码效率低,执行效率不可能因为这几个判断就低下来吧?
if theflag<>controlflag then '这里就可以确定上次鼠标所在控件,即鼠标"离开"了哪个控件 debug.print "离开了:" & controlflag , "进入了:" & theflag controlflag=theflag '忘了加这一句 end if
Private Const TME_LEAVE = &H2Private Type TrackMouseEvent cbSize As Long dwFlags As Long hwndTrack As Long dwHoverTime As Long End Type'当在指定时间内鼠标指针离开或盘旋在一个窗口上时,此函数寄送消息 Private Declare Function TrackMouseEvent Lib "user32" _ (lpEventTrack As TrackMouseEvent) As BooleanPrivate Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Dim tme As TrackMouseEvent 'initialize structure tme.cbSize = Len(tme) tme.hwndTrack = Command1.hwnd tme.dwFlags = TME_LEAVE 'start the tracking TrackMouseEvent tme End SubPrivate Sub Form_Load() SubClass Command1.hwnd End SubPrivate Sub Form_Unload(Cancel As Integer) UnSubClass Command1.hwnd End SubOption ExplicitPublic Const GWL_WNDPROC = (-4) Private Const WM_MOUSELEAVE = &H2A3 Private Const WM_MOUSEWHEEL = &H20A Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Public prevWndProc As Long Dim t As BooleanFunction WndProc1(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long If Msg = WM_MOUSEWHEEL Then If wParam > 0 Then Form1.Text1.Text = Form1.Text1.Text + 1 Else If Form1.Text1.Text > 0 Then Form1.Text1.Text = Form1.Text1.Text - 1 End If End If WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam, lParam)
End Function Function WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long If Msg = WM_MOUSELEAVE Then Debug.Print "leave", Now End If WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam, lParam)
End Function Public Sub SubClass(ByVal hwnd As Long) prevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WndProc) End SubPublic Sub UnSubClass(ByVal hwnd As Long) prevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, prevWndProc) End Sub
在物件上層容器中的MOUSEMOVE中判斷範圍去執行你要的程序
对了,是IMAGE
Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.Caption = "鼠标在按钮上"
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.Caption = "鼠标不在按钮上"
End Sub
Private Declare Function SetCapture Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" () As LongPrivate Sub Cmd1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) With Cmd1
If (X < 0) Or (Y < 0) Or (X > .Width) Or (Y > .Height) Then
ReleaseCapture
' 放入鼠标离开的代码
.Caption = "Out"
Else
SetCapture .hWnd
' 放入鼠标进入的代码
.Caption = "in"
End If
End With
End Sub
这个方法已经用过了,我同一个Form有很多个 image ,用Form的MOVE 事情,太慢了。。
如果有二十个控件,,
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.Caption = "鼠标不在按钮上"
Command2.Caption = "鼠标不在按钮上"
Command3.Caption = "鼠标不在按钮上"
...
Command20.Caption = "鼠标不在按钮上" End Sub
这样效率有点低。
用timer如何来监测呢。。
type pointapi
x as long
y as long
end type引用windowfrompoint和getcursorpos API
private sub timer1_timer()
dim hcursorwnd as long,point as pointapi
getcursorpos point
hcursorwnd=windowfrompoint(point.x,point.y)
if point.x and point.y 在commandbutton上 then
...
else
...
end if
end sub
Private Declare Function ReleaseCapture Lib "user32" () As LongDim obj As ObjectPrivate Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If obj Is Nothing Then
Exit Sub
End If
If X < obj.Left Or X > obj.Left + obj.Width Or Y < obj.Top Or Y > obj.Top + obj.Height Then
ReleaseCapture
obj.Caption = "离开了"
Set obj = Nothing
End If
End SubPrivate Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
SetCapture Me.hWnd
Set obj = Command1
Command1.Caption = "进来了"
End Sub
Private Sub Frame1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
SetCapture Me.hWnd
Set obj = Frame1
Frame1.Caption = "进来了"
End SubPrivate Sub Label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
SetCapture Me.hWnd
Set obj = Label1
Label1.Caption = "进来了"
End SubPrivate Sub Label2_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
SetCapture Me.hWnd
Set obj = Label2
Label2.Caption = "进来了"
End Sub
Private Sub Label3_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
SetCapture Me.hWnd
Set obj = Label3
Label3.Caption = "进来了"
End Sub
With tTrackMouse
.cbSize = Len(tTrackMouse)
.dwFlags = TME_LEAVE
.hwndTrack = 控件.hwnd
End With这样,当鼠标离开该控件,系统会给其发WM_MOUSELEAVE消息,这样就可以得知了。
注意,需要设置一个标志,避免在WM_MOUSEMOVE里多次调用TrackMouseEvent。
if theflag<>controlflag then
'这里就可以确定上次鼠标所在控件,即鼠标"离开"了哪个控件
debug.print "离开了:" & controlflag , "进入了:" & theflag
end if
end subprivate sub Image1_MouseMove(xxxxxxxxxxxxxxxxxx)
call getmouse("Image1") '每个控件的MOUSEMOVE事件里加这一句即可
'其它内容
end sub
这样子结构好些.话又说回来,最多是编码效率低,执行效率不可能因为这几个判断就低下来吧?
'这里就可以确定上次鼠标所在控件,即鼠标"离开"了哪个控件
debug.print "离开了:" & controlflag , "进入了:" & theflag
controlflag=theflag '忘了加这一句
end if
cbSize As Long
dwFlags As Long
hwndTrack As Long
dwHoverTime As Long
End Type'当在指定时间内鼠标指针离开或盘旋在一个窗口上时,此函数寄送消息
Private Declare Function TrackMouseEvent Lib "user32" _
(lpEventTrack As TrackMouseEvent) As BooleanPrivate Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim tme As TrackMouseEvent
'initialize structure
tme.cbSize = Len(tme)
tme.hwndTrack = Command1.hwnd
tme.dwFlags = TME_LEAVE
'start the tracking
TrackMouseEvent tme
End SubPrivate Sub Form_Load()
SubClass Command1.hwnd
End SubPrivate Sub Form_Unload(Cancel As Integer)
UnSubClass Command1.hwnd
End SubOption ExplicitPublic Const GWL_WNDPROC = (-4)
Private Const WM_MOUSELEAVE = &H2A3
Private Const WM_MOUSEWHEEL = &H20A
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public prevWndProc As Long
Dim t As BooleanFunction WndProc1(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg = WM_MOUSEWHEEL Then
If wParam > 0 Then
Form1.Text1.Text = Form1.Text1.Text + 1
Else
If Form1.Text1.Text > 0 Then Form1.Text1.Text = Form1.Text1.Text - 1
End If
End If
WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam, lParam)
End Function
Function WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg = WM_MOUSELEAVE Then
Debug.Print "leave", Now
End If
WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam, lParam)
End Function
Public Sub SubClass(ByVal hwnd As Long)
prevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WndProc)
End SubPublic Sub UnSubClass(ByVal hwnd As Long)
prevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, prevWndProc)
End Sub