Vba 使用SetWindowsHookEx。在Excel 2010中

Vba 使用SetWindowsHookEx。在Excel 2010中,vba,excel,hook,setwindowshookex,Vba,Excel,Hook,Setwindowshookex,这个功能让我抓狂!我试图使用SetWindwosHookEx来避免用户的一些击键,但我无法使其正常工作 我一直在网上寻找很多代码,但我不明白为什么它不适合我。首先,这是因为我使用的是Excel 2010(64位),而我的代码不适用于它,但现在我不知道 基本上,我已经创建了一个简单的代码,当我拉“g”时,它会显示一条消息,但当拉任意键时,Excel会崩溃。当我一步一步地运行代码时,它不会崩溃,但是如果我拉“g”,消息会出现三次 这是我的代码: #If Win64 Then Public Decl

这个功能让我抓狂!我试图使用SetWindwosHookEx来避免用户的一些击键,但我无法使其正常工作

我一直在网上寻找很多代码,但我不明白为什么它不适合我。首先,这是因为我使用的是Excel 2010(64位),而我的代码不适用于它,但现在我不知道

基本上,我已经创建了一个简单的代码,当我拉“g”时,它会显示一条消息,但当拉任意键时,Excel会崩溃。当我一步一步地运行代码时,它不会崩溃,但是如果我拉“g”,消息会出现三次

这是我的代码:

#If Win64 Then

Public Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As LongPtr) As LongPtr
Public Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As LongPtr, ByVal lpFn As LongPtr, ByVal hmod As LongPtr, ByVal dwThreadId As LongPtr) As LongPrt
Public Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As LongPtr, ByVal nCode As LongPtr, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Public Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
Public Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As LongPtr
Public Declare PtrSafe Function GetKeyState Lib "user32" (ByVal nVirtKey As LongPtr) As Integer
Private hWndPPT As LongPtr
Private HookHandle As LongPtr

'ADICIONAL
Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (ByVal hDlg As LongPrt, ByVal nIDDlgItem As LongPtr, ByVal wMsg As LongPtr, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As LongPtr) As LongPtr



#Else
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
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 CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private hWndPPT As Long
Private HookHandle As Long

'ADICIONAL
Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

#End If



'Constants to be used in our API functions
'Private Const EM_SETPASSWORDCHAR = &HCC
'Private Const WH_CBT = 5
Private Const WH_KEYBOARD = 2
'Private Const HCBT_ACTIVATE = 5
Private Const HC_ACTION = 0

'Private hHook As Long


Public Sub RemoveHook()
    UnhookWindowsHookEx (HookHandle)
End Sub

Sub SetHook()
#If Win64 Then
Dim lThreadID As LongPtr
Dim lngModHwnd As LongPtr
#Else
Dim lThreadID As Long
Dim lngModHwnd As Long
#End If

lThreadID = GetCurrentThreadId
lngModHwnd = GetModuleHandle(vbNullString)

'Set a local hook
HookHandle = SetWindowsHookEx(WH_KEYBOARD, AddressOf NewProc, 0, lThreadID)
End Sub

Public Function NewProc(ByVal lngCode As LongPtr, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr

    If lngCode < HC_ACTION Then
      NewProc = CallNextHookEx(HookHandle, lngCode, wParam, lParam)
      Exit Function
    End If

    If wParam = 71 Then
        'MsgBox "g"
        'NewProc = 1
        wParam = 70
        'Exit Function
    End If

    'This line will ensure that any other hooks that may be in place are
    'called correctly.
    CallNextHookEx HookHandle, lngCode, wParam, lParam

End Function
#如果是Win64那么
公共声明PtrSafe函数unhookwindowshookx Lib“user32”(ByVal hHook作为LongPtr)作为LongPtr
将PtrSafe函数SetWindowsHookEx Lib“user32”别名“setWindowsHookxa”(ByVal idHook作为LongPtr,ByVal lpFn作为LongPtr,ByVal hmod作为LongPtr,ByVal dwThreadId作为LongPtr)公开声明为LongPrt
公共声明PtrSafe函数调用nexthookex Lib“user32”(ByVal hHook作为LongPtr,ByVal nCode作为LongPtr,ByVal wParam作为LongPtr,lParam作为任意)作为LongPtr
将PtrSafe函数GetModuleHandle Lib“kernel32”别名“GetModuleHandleA”(ByVal lpModuleName作为字符串)公开声明为LongPtr
公共声明PtrSafe函数GetCurrentThreadId Lib“kernel32”()为LongPtr
将PtrSafe函数GetKeyState Lib“user32”(ByVal nVirtKey作为LongPtr)公开声明为整数
专用hWndPPT作为长PTR
专用钩柄作为长柄
“再见
私有声明函数senddlgitemmessagelib“user32”别名“senddlgitemessagea”(ByVal hDlg作为LongPrt,ByVal nIDDlgItem作为LongPtr,ByVal wMsg作为LongPtr,ByVal wParam作为LongPtr,ByVal lParam作为LongPtr)作为LongPtr
将私有函数GetClassName Lib“user32”别名“GetClassNameA”(ByVal hwnd作为LongPtr,ByVal lpClassName作为String,ByVal nMaxCount作为LongPtr)声明为LongPtr
#否则
公共声明函数unhookwindowshookx Lib“user32”(ByVal hHook作为Long)作为Long
公共声明函数setWindowshookx Lib“user32”别名“setWindowshookxa”(ByVal idHook为Long,ByVal lpFn为Long,ByVal hmod为Long,ByVal dwThreadId为Long)为Long
公共声明函数CallNextHookEx Lib“user32”(ByVal hHook为Long,ByVal nCode为Long,ByVal wParam为Long,lParam为Any)为Long
公共声明函数GetModuleHandle Lib“kernel32”别名“GetModuleHandleA”(ByVal lpModuleName作为字符串)的长度为
公共声明函数GetCurrentThreadId Lib“kernel32”(长度为
将函数GetKeyState Lib“user32”(ByVal nVirtKey长度)声明为整数
私人hWndPPT,只要
私用钩柄,只要
“再见
私有声明函数senddlgitemessage Lib“user32”别名“senddlgitemessagea”(ByVal hDlg为Long,ByVal nIDDlgItem为Long,ByVal wMsg为Long,ByVal wParam为Long,ByVal lParam为Long)为Long
私有声明函数GetClassName Lib“user32”别名“GetClassNameA”(ByVal hwnd为Long,ByVal lpClassName为String,ByVal nMaxCount为Long)为Long
#如果结束
'将在我们的API函数中使用的常量
'Private Const EM_SETPASSWORDCHAR=&HCC
'专用常量WH_CBT=5
专用常量WH_键盘=2
'专用常量HCBT_激活=5
私有常量HC_ACTION=0
“二等兵,只要你愿意
公共子移除钩子()
Unhookwindowshookx(钩柄)
端接头
子集钩()
#如果是Win64,那么
作为LongPtr的Dim-lthreaid
变暗lngModHwnd为长PTR
#否则
我的名字和readid一样长
变暗lngModHwnd尽可能长
#如果结束
lThreadID=GetCurrentThreadId
lngModHwnd=GetModuleHandle(vbNullString)
"设地方钩",
HookHandle=SetWindowsHookEx(WH_键盘,NewProc的地址,0,lThreadID)
端接头
公共函数NewProc(ByVal lngCode作为LongPtr,ByVal wParam作为LongPtr,ByVal lParam作为LongPtr)作为LongPtr
如果lngCode
64位的正确声明为:

Public Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As LongPtr) As Long
Public Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpFn As LongPtr, ByVal hmod As LongPtr, ByVal dwThreadId As Long) As LongPtr
Public Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As LongPtr, ByVal nCode As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Public Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
Public Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare PtrSafe Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

实际上,我看不出您发布的代码在64位上是如何运行的。

您需要查看您的声明-并非所有内容都应该是
LongPtr
。那些应该是
LongPtr
而不是
LongPrt
。很抱歉我的无知,但哪些不是LongPtr?这是我第一次为64位编码。谢谢,谢谢!。事实上,它并没有真正起作用。一旦我按下一个键,代码就会进入一个不可阻挡的循环。在准备好关于hook、setwindowsex、callnexthookex等的信息和许多代码后,我看不到错误。所有示例代码看起来都很简单,但我无法让它再次工作。嗨,我做了一些改进,这段代码几乎可以正常工作,但有两个问题:当我运行代码时,该函数不返回我正在提取的密钥,因此不会写入任何内容,“NewProc_64”函数会运行两次: