如何得知Mouse已离开某物件(Mouse Hook)

本文介绍了一种利用Mouse Hook技术解决鼠标进入和离开控件时触发特定行为的方法。通过设置本地Hook监听所有鼠标事件,并检查鼠标坐标来判断鼠标是否位于指定控件范围内。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


  来源:cww  
   
  常见到某些软体,当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  

  1. Option   Explicit   
  2.     
  3.   Public   Const   WM_MOUSEMOVE   =   &H200   
  4.   Public   Const   WH_MOUSE   =   7   
  5.     
  6.   Type   POINTAPI   
  7.   X   As   Long   
  8.   Y   As   Long   
  9.   End   Type   
  10.   Type   MOUSEHOOKSTRUCT   
  11.   pt   As   POINTAPI   
  12.   hwnd   As   Long   
  13.   wHitTestCode   As   Long   
  14.   dwExtraInfo   As   Long   
  15.   End   Type   
  16.   Type   RECT   
  17.   Left   As   Long   
  18.   Top   As   Long   
  19.   Right   As   Long   
  20.   Bottom   As   Long   
  21.   End   Type   
  22.     
  23.   Declare   Function   SetWindowsHookEx   Lib   "user32"   Alias   _   
  24.         "SetWindowsHookExA"   (ByVal   idHook   As   Long,   ByVal   lpfn   As   Long,   _   
  25.         ByVal   hmod   As   Long,   ByVal   dwThreadId   As   Long)   As   Long   
  26.   Declare   Function   UnhookWindowsHookEx   Lib   "user32"   _   
  27.         (ByVal   hHook   As   Long)   As   Long   
  28.   Declare   Function   CallNextHookEx   Lib   "user32"   (ByVal   hHook   As   Long,   _   
  29.         ByVal   nCode   As   Long,   ByVal   wParam   As   Long,   lParam   As   Any)   As   Long   
  30.   Declare   Sub   CopyMemory   Lib   "KERNEL32"   Alias   "RtlMoveMemory"   _   
  31.       (lpvDest   As   Any,   ByVal   lpvSource   As   Long,   ByVal   cbCopy   As   Long)   
  32.   Declare   Function   ScreenToClient   Lib   "user32"   (ByVal   hwnd   As   Long,   lpPoint   As   POINTAPI)   As   Long   
  33.   Public   theForm   As   Form   
  34.   Public   hHook   As   Long       '   handle   of   Hook   Procedure   
  35.   Public   imgRect   As   RECT   
  36.   Sub   EnableHook(ctl   As   Control)   
  37.         If   hHook   =   0   Then   
  38.               imgRect.Top   =   ctl.Top   
  39.               imgRect.Left   =   ctl.Left   
  40.               imgRect.Right   =   imgRect.Left   +   ctl.Width   
  41.               imgRect.Bottom   =   imgRect.Top   +   ctl.Height   
  42.               hHook   =   SetWindowsHookEx(WH_MOUSE,   AddressOf   MouseHookProc,   App.hInstance,   App.ThreadID)   
  43.         End   If   
  44.   End   Sub   
  45.   Sub   FreeHook()   
  46.   Dim   ret   As   Long   
  47.   If   hHook   <>   0   Then   
  48.         ret   =   UnhookWindowsHookEx(hHook)   
  49.         hHook   =   0   
  50.   End   If   
  51.   End   Sub   
  52.   Function   MouseHookProc(ByVal   code   As   Long,   ByVal   wParam   As   Long,   _   
  53.   ByVal   lParam   As   Long)   As   Long   
  54.     Dim   mStru   As   MOUSEHOOKSTRUCT,   i   As   Long   
  55.     If   wParam   =   WM_MOUSEMOVE   Then   
  56.           CopyMemory   mStru,   lParam,   LenB(mStru)   
  57.           'mStru.pt的座标是萤幕座标,所以要经转换成相对於Form的座标   
  58.           Call   ScreenToClient(Screen.ActiveForm.hwnd,   mStru.pt)   
  59.     
  60.           '不在imgButton之内   
  61.           If   Not   (mStru.pt.Y   >=   imgRect.Top   And   mStru.pt.Y   <=   imgRect.Bottom   And   _   
  62.                 mStru.pt.X   >=   imgRect.Left   And   mStru.pt.X   <=   imgRect.Right)   Then   
  63.                 MouseHookProc   =   0   
  64.                 Call   CallNextHookEx(hHook,   code,   wParam,   lParam)   
  65.                 Call   FreeHook   
  66.                 Debug.Print   "Out   of   The   Range   "   
  67.                 Exit   Function   
  68.           Else   
  69.                 Debug.Print   "In   The   Range"   
  70.           End   If   
  71.     End   If   
  72.     MouseHookProc   =   0   '表示要处理这个讯息   
  73.     Call   CallNextHookEx(hHook,   code,   wParam,   lParam)   
  74.   End   Function   
  75.     
  76.   '以下在Form,需一个Command1   
  77.   Private   Sub   Command1_MouseMove(Button   As   Integer,   Shift   As   Integer,   X   As   Single,   Y   As   Single)   
  78.   Call   EnableHook(Command1)   
  79.   End   Sub   
  80.     
  81.   Private   Sub   Form_Load()   
  82.   Me.ScaleMode   =   3   
  83.   End   Sub   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值