新聞| | PChome| 登入
2007-10-25 23:56:02 | 人氣143| 回應0 | 上一篇 | 下一篇
推薦 0 收藏 0 轉貼0 訂閱站台

如何得知Mouse已離開某物件(Mouse Hook)

來源: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
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

                                                        

台長: Kenny
人氣(143) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 教育學習(進修、留學、學術研究、教育概況) | 個人分類: 程式設計 |
此分類下一篇:如何使鍵盤、Mouse失效(JournalPlayBack Hook)
此分類上一篇:如何得知Mouse已離開某物件(二)

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文