'这样可以做全局键盘钩子,不知实现的功能是否是你说的全局Public 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 Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, ByVal lpvSource As Long, ByVal cbCopy As Long) Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPublic Const SW_SHOW = 5 Public Const SW_HIDE = 0 Public Const SW_RESTORE = 9Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As LongType EVENTMSG message As Long paramL As Long paramH As Long time As Long hwnd As Long End TypePublic Const WH_KEYBOARD_LL = 13 Public Const Alt_Down = &H20'消息 Public Const HC_ACTION = 0 Public Const HC_SYSMODALOFF = 5 Public Const HC_SYSMODALON = 4Public Const WM_KEYDOWN = &H100 Public Const WM_KEYUP = &H101 Public Const WM_SYSKEYDOWN = &H104 Public Const WM_SYSKEYUP = &H105Public msg As EVENTMSGPublic lHook As Long Public lNum As Long Public Function CallHookProc(ByVal code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Dim bflag As Boolean bflag = False If code = HC_ACTION Then CopyMemory msg, lParam, LenB(msg) Select Case wParam Case WM_SYSKEYDOWN, WM_SYSKEYUP, WM_KEYDOWN, WM_KEYUP: 'Win键 Menu键 bflag = (msg.message = 91) Or (msg.message = 92) Or (msg.message = 93) 'Ctrl+ESC bflag = bflag Or ((GetKeyState(vbKeyControl) And &H8000) <> 0 And (msg.message = vbKeyEscape)) 'Alt+Tab bflag = bflag Or ((msg.message = vbKeyTab) And (msg.paramH And Alt_Down) <> 0) 'Alt+ESC bflag = bflag Or ((msg.paramH And Alt_Down) <> 0 And (msg.message = vbKeyEscape)) End Select End If
If bflag = True Then CallHookProc = 1 Else CallHookProc = 0 End If
If code <> 0 Then CallHookProc = CallNextHookEx(0, code, wParam, lParam) End If’加钩子 lHook = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf CallHookProc, App.hInstance, 0)‘卸钩子 If lHook <> 0 Then UnhookWindowsHookEx lHook End If
我这有段代码,能否解释一下,为什么在调试时是好的,编译成 exe 后就不行了呢? ======================== Private Type POINTAPI X As Long Y As Long End Type Private Declare Function SetCapture Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function ReleaseCapture Lib "user32" () As Long Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long Dim Pt As POINTAPI Private Sub Form_Load() 'redirect all mouse input to this form SetCapture Me.hwnd End Sub Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) ReleaseCapture SetCapture Me.hwnd End Sub Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) 'Get the current cursor position GetCursorPos Pt Me.CurrentX = 0 Me.CurrentY = 0 'Clear the screen Me.Cls Me.Print "Cursor position:" 'Print the mouse coördinates to the form Me.Print "X:" + Str$(Pt.X) + " Y:" + Str$(Pt.Y) Me.Print " (Press ALT-F4 to unload this form)" SetCapture Me.hwnd End Sub Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) ReleaseCapture SetCapture Me.hwnd End Sub=============================================================================== 编译成 exe 后 ,SetCapture 失去了该有的作用.(本来应该在窗体外面也能打印出鼠标坐标的,调试的时候是可以的)为什么?
End SubPrivate Sub Form_DblClick() '卸钩子,一定要卸,否则VB本身崩溃 If lHook <> 0 Then UnhookWindowsHookEx lHook End If Unload Me
End Sub ’--- ‘模块'--------- Public 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 Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, ByVal lpvSource As Long, ByVal cbCopy As Long) Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPublic Const SW_SHOW = 5 Public Const SW_HIDE = 0 Public Const SW_RESTORE = 9Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As LongType EVENTMSG message As Long paramL As Long paramH As Long time As Long hwnd As Long End TypePrivate Type POINTAPI x As Long y As Long End TypePublic Const WH_KEYBOARD_LL = 13 Public Const WH_MOUSE_LL = 14 Public Const Alt_Down = &H20 Public Const WH_MOUSE = 7'消息 Public Const HC_ACTION = 0 Public Const HC_SYSMODALOFF = 5 Public Const HC_SYSMODALON = 4Public Const WM_KEYDOWN = &H100 Public Const WM_KEYUP = &H101 Public Const WM_SYSKEYDOWN = &H104 Public Const WM_SYSKEYUP = &H105 Private Const WM_MOUSEMOVE = &H200Public msgs As EVENTMSGPublic lHook As Long Public lNum As Long'注意,该程序里的代码一旦有错,它会使VB本身崩溃,所以... Public Function CallHookProc(ByVal code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Dim pt As POINTAPI
bflag = False If code = HC_ACTION Then CopyMemory msgs, lParam, LenB(msgs) Select Case wParam Case WM_MOUSEMOVE pt.x = msgs.message '我试的,可是好奇怪。它就是X pt.y = msgs.paramL 'Y '你在窗体添一个TextBox Form1.Text1 = Str(pt.x) + "," + Str(pt.y) '它确实显示了正确的鼠标位置 '既然有鼠标位置,你的程序也就解决了 End Select End If ' If code <> 0 Then CallHookProc = CallNextHookEx(0, code, wParam, lParam) End If
End Function
GOOD !非常好! WH_MOUSE_LL 我在 MSDN 中有看到,只是思想放松了,认为不是我要的,就没有试再次感谢
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, ByVal lpvSource As Long, ByVal cbCopy As Long)
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPublic Const SW_SHOW = 5
Public Const SW_HIDE = 0
Public Const SW_RESTORE = 9Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As LongType EVENTMSG
message As Long
paramL As Long
paramH As Long
time As Long
hwnd As Long
End TypePublic Const WH_KEYBOARD_LL = 13
Public Const Alt_Down = &H20'消息
Public Const HC_ACTION = 0
Public Const HC_SYSMODALOFF = 5
Public Const HC_SYSMODALON = 4Public Const WM_KEYDOWN = &H100
Public Const WM_KEYUP = &H101
Public Const WM_SYSKEYDOWN = &H104
Public Const WM_SYSKEYUP = &H105Public msg As EVENTMSGPublic lHook As Long
Public lNum As Long
Public Function CallHookProc(ByVal code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim bflag As Boolean
bflag = False
If code = HC_ACTION Then
CopyMemory msg, lParam, LenB(msg)
Select Case wParam
Case WM_SYSKEYDOWN, WM_SYSKEYUP, WM_KEYDOWN, WM_KEYUP:
'Win键 Menu键
bflag = (msg.message = 91) Or (msg.message = 92) Or (msg.message = 93)
'Ctrl+ESC
bflag = bflag Or ((GetKeyState(vbKeyControl) And &H8000) <> 0 And (msg.message = vbKeyEscape))
'Alt+Tab
bflag = bflag Or ((msg.message = vbKeyTab) And (msg.paramH And Alt_Down) <> 0)
'Alt+ESC
bflag = bflag Or ((msg.paramH And Alt_Down) <> 0 And (msg.message = vbKeyEscape))
End Select
End If
If bflag = True Then
CallHookProc = 1
Else
CallHookProc = 0
End If
If code <> 0 Then
CallHookProc = CallNextHookEx(0, code, wParam, lParam)
End If’加钩子
lHook = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf CallHookProc, App.hInstance, 0)‘卸钩子
If lHook <> 0 Then
UnhookWindowsHookEx lHook
End If
End Function
========================
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Declare Function SetCapture Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Dim Pt As POINTAPI
Private Sub Form_Load()
'redirect all mouse input to this form
SetCapture Me.hwnd
End Sub
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
ReleaseCapture
SetCapture Me.hwnd
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
'Get the current cursor position
GetCursorPos Pt
Me.CurrentX = 0
Me.CurrentY = 0
'Clear the screen
Me.Cls
Me.Print "Cursor position:"
'Print the mouse coördinates to the form
Me.Print "X:" + Str$(Pt.X) + " Y:" + Str$(Pt.Y)
Me.Print " (Press ALT-F4 to unload this form)"
SetCapture Me.hwnd
End Sub
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
ReleaseCapture
SetCapture Me.hwnd
End Sub===============================================================================
编译成 exe 后 ,SetCapture 失去了该有的作用.(本来应该在窗体外面也能打印出鼠标坐标的,调试的时候是可以的)为什么?
说明:SetCapture函数向属于当前线程的给定窗口设置鼠标捕获。一旦某一窗口捕获了鼠标,则不管光标是否在该窗口的边界内,所有鼠标输入都直接对着该窗口。同时只能有一个窗口捕获鼠标。
若鼠标光标正在其他线程创建的窗口之上,则仅当按下了一个鼠标按钮时,系统才将鼠标输入指向给定的窗口。
参数:hwnd 标识当前线程中将捕获鼠标的窗口。
返回值:若函数成功,返回值是原来捕获鼠标的窗口的句柄。若没有这个窗口,则返回值为NULL。
注释:只有前台窗口可捕获鼠标。当后台窗口试图这样做时,该窗口只能接收光标热点位于该窗口可见部分中时发生的鼠标事件的消息。另外,即使前台窗口未捕获鼠标,用户也可单击另一个窗口使其进入前台。
当窗口不再需要所有鼠标输入时,创建该窗口的线程应调用PeleaseCapture函数释放鼠标。
不得调用该函数为其它过程捕获鼠标输入。按这样的解释应该不会出现上面的情况,但是为什么出现了呢?
Win2000 sp3 VB6.0
http://expert.csdn.net/Expert/topic/1663/1663477.xml?temp=.3203852
由于在VB中,大家都用WH_MOUSE参数加鼠标钩子,而此钩子不是全局钩子
要使用在API参数中找不到的WH_MOUSE_LL。‘----------sub form_load()
'加钩子
'注意是WH_MOUSE_LL,不是WH_MOUSE,WH_MOUSE_LL是我在VC头文件中搜索到的!!!
'WH_MOUSE不是全局,只对本身有效,你可以与WH_MOUSE_LL比较试试
lHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf CallHookProc, App.hInstance, 0)
End SubPrivate Sub Form_DblClick()
'卸钩子,一定要卸,否则VB本身崩溃
If lHook <> 0 Then
UnhookWindowsHookEx lHook
End If Unload Me
End Sub
’---
‘模块'---------
Public 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
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, ByVal lpvSource As Long, ByVal cbCopy As Long)
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPublic Const SW_SHOW = 5
Public Const SW_HIDE = 0
Public Const SW_RESTORE = 9Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As LongType EVENTMSG
message As Long
paramL As Long
paramH As Long
time As Long
hwnd As Long
End TypePrivate Type POINTAPI
x As Long
y As Long
End TypePublic Const WH_KEYBOARD_LL = 13
Public Const WH_MOUSE_LL = 14
Public Const Alt_Down = &H20
Public Const WH_MOUSE = 7'消息
Public Const HC_ACTION = 0
Public Const HC_SYSMODALOFF = 5
Public Const HC_SYSMODALON = 4Public Const WM_KEYDOWN = &H100
Public Const WM_KEYUP = &H101
Public Const WM_SYSKEYDOWN = &H104
Public Const WM_SYSKEYUP = &H105
Private Const WM_MOUSEMOVE = &H200Public msgs As EVENTMSGPublic lHook As Long
Public lNum As Long'注意,该程序里的代码一旦有错,它会使VB本身崩溃,所以...
Public Function CallHookProc(ByVal code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim pt As POINTAPI
bflag = False
If code = HC_ACTION Then
CopyMemory msgs, lParam, LenB(msgs)
Select Case wParam
Case WM_MOUSEMOVE
pt.x = msgs.message '我试的,可是好奇怪。它就是X
pt.y = msgs.paramL 'Y
'你在窗体添一个TextBox
Form1.Text1 = Str(pt.x) + "," + Str(pt.y) '它确实显示了正确的鼠标位置
'既然有鼠标位置,你的程序也就解决了 End Select
End If
'
If code <> 0 Then
CallHookProc = CallNextHookEx(0, code, wParam, lParam)
End If
End Function
WH_MOUSE_LL 我在 MSDN 中有看到,只是思想放松了,认为不是我要的,就没有试再次感谢