网页功能: 加入收藏 设为首页 网站搜索  
如何得知Mouse已离开某物件(Mouse Hook)
发表日期:2002-12-08作者:[] 出处:  

常见到某些软体,当Mouse进入其区域时,会启动某个行为,Mouse离开时,又有其他的

动作,例如Cool Bar,当Mouse移入时,Button会上升,离开时Button水变平面。

第一个想到的是在物件的MouseMove中设定进入的行为,这没有问题,但离开呢?有几

个想法:1.如果该物件在Form上,可以在Form的MouseMove上作离开的动作。2.於该物

件的MouseMove上Check是否Mouse的座标已在物件的边缘,若是则执行离开的动作。

但这两者,都会遇上一个问题,如果Mouse的移动很快,使得MouseMove的Event根本没

有在该物件或Form上面发生,那就不可行了;所以看来简单的问题又变复杂了,那只好

使用Mouse Hook来做。

Mouse Hook是拦截硬体所产生Mouse硬体的讯息,不管Mouse现在於何处,都会将Mouse的

讯息送往Hook Procedure,当然,一般情况下,是於该程式正处於Active的情况下

(Local Hook),讯息才会送往该Hook Procedure,如果别的程式所产生的Mouse讯息也要

进入该Hook Function时,那便得使用Remote Hook,而Remote Hook的方式,是要把Hook

Procedure放在.Dll之中,而Local Hook只要把 Hook Procedure放在.Bas之中便可以了。

因挂上了Mouse Hook(Local),所以该程式执行时所有的Mouse 的讯息便会送往该Hook

Function,而且有包含Mouse所在的座标(相对於Screen),於是我们可以Check Mouse

的座标,进而得知Mouse是否仍在物件范围。

Please Reference : 如何得知Mouse已离开某物件(二)

'以下在.Bas

Option Explicit

Public Const WM_MOUSEMOVE = &H200

Public Const WH_MOUSE = 7

Type POINTAPI

X As Long

Y As Long

End Type

Type MOUSEHOOKSTRUCT

pt As POINTAPI

hwnd As Long

wHitTestCode As Long

dwExtraInfo As Long

End Type

Type RECT

Left As Long

Top As Long

Right As Long

Bottom As Long

End Type

Declare Function SetWindowsHookEx Lib "user32" Alias _

  "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _

  ByVal hmod As Long, ByVal dwThreadId As Long) As Long

Declare Function UnhookWindowsHookEx Lib "user32" _

  (ByVal hHook As Long) As Long

Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _

  ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long

Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" _

 (lpvDest As Any, ByVal lpvSource As Long, ByVal cbCopy As Long)

Declare Function ScreenToClient Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long

Public theForm As Form

Public hHook As Long  ' handle of Hook Procedure

Public imgRect As RECT

Sub EnableHook(ctl As Control)

  If hHook = 0 Then

   imgRect.Top = ctl.Top

   imgRect.Left = ctl.Left

   imgRect.Right = imgRect.Left + ctl.Width

   imgRect.Bottom = imgRect.Top + ctl.Height

   hHook = SetWindowsHookEx(WH_MOUSE, AddressOf MouseHookProc, App.hInstance, App.ThreadID)

  End If

End Sub

Sub FreeHook()

Dim ret As Long

If hHook <> 0 Then

  ret = UnhookWindowsHookEx(hHook)

  hHook = 0

End If

End Sub

Function MouseHookProc(ByVal code As Long, ByVal wParam As Long, _

ByVal lParam As Long) As Long

Dim mStru As MOUSEHOOKSTRUCT, i As Long

If wParam = WM_MOUSEMOVE Then

  CopyMemory mStru, lParam, LenB(mStru)

  'mStru.pt的座标是萤幕座标,所以要经转换成相对於Form的座标

  Call ScreenToClient(Screen.ActiveForm.hwnd, mStru.pt)

  '不在imgButton之内

  If Not (mStru.pt.Y >= imgRect.Top And mStru.pt.Y <= imgRect.Bottom And _

    mStru.pt.X >= imgRect.Left And mStru.pt.X <= imgRect.Right) Then

    MouseHookProc = 0

    Call CallNextHookEx(hHook, code, wParam, lParam)

    Call FreeHook

    Debug.Print "Out of The Range "

    Exit Function

  Else

    Debug.Print "In The Range"

  End If

End If

MouseHookProc = 0 '表示要处理这个讯息

Call CallNextHookEx(hHook, code, wParam, lParam)

End Function

'以下在Form,需一个Command1

Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)

Call EnableHook(Command1)

End Sub

Private Sub Form_Load()

Me.ScaleMode = 3

End Sub

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 如何得知Mouse已离开某物件(Mouse Hook)
本类热点文章
  揭穿号称内存占用极低的软件的诡计
  用VB6实现真正实用的多线程处理
  读写INI文件的四个函数
  shell函数能以同步方式打开一个exe文件
  VB的API编程精粹
  TAPI笔记
  锁定计算机
  巧用API函数增强VB位操作功能
  在VB中使用API函数
  让你的文本框“聪明”一点
  关机消息的拦截
  在WIN2000下实现程序的关机
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2019 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00402