检测Vb6外部的按键

检测Vb6外部的按键,vb6,Vb6,我目前正在修改一个运行WindowsServer2K的非常旧的系统。我正在研究的一个要求是阻止在另一个程序的某个窗口按下我们无法修改的键盘 一般来说,我的过程是很好的,因为我检测到按键,然后在出现按键时终止窗口,但是我发现并使用的唯一工作代码会导致很多问题,有时Control/Windows Key/etc会卡住,整个系统会出现奇怪的行为。这是我用于钩子的代码: Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As

我目前正在修改一个运行WindowsServer2K的非常旧的系统。我正在研究的一个要求是阻止在另一个程序的某个窗口按下我们无法修改的键盘

一般来说,我的过程是很好的,因为我检测到按键,然后在出现按键时终止窗口,但是我发现并使用的唯一工作代码会导致很多问题,有时Control/Windows Key/etc会卡住,整个系统会出现奇怪的行为。这是我用于钩子的代码:

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 UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Declare Function SetWindowsHook Lib "user32" Alias "SetWindowsHookA" (ByVal nFilterType As Long, ByVal pfnFilterProc 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 Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Global Const WH_KEYBOARD_LL = 13

Public hook As Long

Public Const HC_ACTION = 0
Type HookStruct
    vkCode As Long
    scancode As Long
    FLAGS As Long
    time As Long
    dwExtraInfo As Long
End Type

Public active As Boolean
Public value As String

Public Function myfunc(ByVal code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Dim kybd As HookStruct

    myfunc = True


    If code = HC_ACTION And wParam <> 257 Then
            If active Then

            'SendKeys "{ESC}"
            'MsgBox ("keypressed")
            End If

        myfunc = CallNextHookEx(hook, code, wParam, lParam)
    ElseIf code < 0 Then
        myfunc = CallNextHookEx(hook, code, wParam, lParam)
    End If

End Function
Public Declare Function CallNextHookEx Lib“user32”(ByVal hHook尽可能长,ByVal nCode尽可能长,ByVal wParam尽可能长,lParam尽可能长)尽可能长
公共声明函数unhookwindowshookx Lib“user32”(ByVal hHook作为Long)作为Long
公共声明函数SetWindowsHook Lib“user32”别名“SetWindowsHookA”(ByVal nFilterType为Long,ByVal pfnFilterProc为Long)为Long
公共声明函数setWindowshookx Lib“user32”别名“setWindowshookxa”(ByVal idHook为Long,ByVal lpfn为Long,ByVal hmod为Long,ByVal dwThreadId为Long)为Long
Public Declare Sub-CopyMemory Lib“kernel32”别名“rtlmovemory”(目标为任意,源为任意,ByVal长度为任意)
全局常量WH\u键盘LL=13
公共挂钩只要
公共常数HC_ACTION=0
类型HookStruct
vkCode尽可能长
扫描码一样长
旗子一样长
时间尽可能长
只要
端型
作为布尔值的公共活动
作为字符串的公共值
公共函数myfunc(ByVal代码为Long,ByVal wParam为Long,ByVal lParam为Long)为Long
作为HookStruct的Dim kybd
myfunc=True
如果代码=HC_动作和wParam 257,则
如果激活,则
'发送键“{ESC}”
'MsgBox(“按键”)
如果结束
myfunc=CallNextHookEx(钩子、代码、wParam、lParam)
ElseIf代码<0则
myfunc=CallNextHookEx(钩子、代码、wParam、lParam)
如果结束
端函数
一般来说,代码正常工作,但是如果按Control、Alt或Windows键,则整个系统可能会失控


是否有更好的方法检测系统外/特定窗口中的按键,甚至可能,或者我在这里做错了什么?

请参阅以下线程:

您可以尝试以下两种方法,看看它们是否更稳定:

RegisterHotKey,定义系统范围热键的函数:

Declare Function RegisterHotKey Lib "user32" Alias "RegisterHotKey" (ByVal hwnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
或GetAsyncKeyState,该函数用于确定调用该函数时键是向上还是向下,以及在上次调用GetAsyncKeyState后是否按下该键:

Declare Function GetAsyncKeyState Lib "user32" Alias "GetAsyncKeyState" (ByVal vKey As Long) As Integer
您可以运行计时器并持续检查GetAsyncKeyState,以查看您要查找的键是否已按下:

Private Sub tmrKeyPressCheck_Timer()
    Dim iCounter As Integer

    For iCounter = 64 To 90
        If CheckKey(iCounter) Then
            txtKeyPressLog.Text = Hour(Now) & ":" & Minute(Now) & ":" & Second(Now) & ": " & Chr(iCounter) & vbCrLf & txtKeyPressLog.Text
        End If
    Next

End Sub

Private Function CheckKey(ByVal p_lngKey As Long) As Boolean
    Dim iReturn As Integer

    iReturn = GetAsyncKeyState(p_lngKey)

    CheckKey = (iReturn <> 0)

End Function
专用子tmrKeyPressCheck_定时器()
作为整数的Dim I计数器
对于iCounter=64到90
如果选择键(iCounter),则
Text=Hour(Now)&“&Minute(Now)&“&Second(Now)&“&Chr(iCounter)&vbCrLf&txtKeyPressLog.Text
如果结束
下一个
端接头
作为布尔值的私有函数CheckKey(ByVal p_lngKey As Long)
变为整数
iReturn=GetAsyncKeyState(p_lngKey)
检查键=(i返回0)
端函数

这是一段代码,它最终没有出现问题:

Private Const WH_KEYBOARD_LL = 13&
Private Const HC_ACTION = 0&
Private Const LLKHF_EXTENDED = &H1&
Private Const LLKHF_INJECTED = &H10&
Private Const LLKHF_ALTDOWN = &H20&
Private Const LLKHF_UP = &H80&

Private Const VK_RIGHT = &H27
Private Const VK_LEFT = &H25
Private Const VK_RSHIFT = &HA1

Private Type KBDLLHOOKSTRUCT
  vkCode As Long
  scanCode As Long
  FLAGS As Long
  time As Long
  dwExtraInfo As Long
End Type

Private 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
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal cb As Long)
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

Public value As String
Public active As Boolean

Public Function HookKeyboard() As Long
    On Error GoTo ErrorHookKeyboard
    m_hDllKbdHook = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf LowLevelKeyboardProc, App.hInstance, 0&)
    HookKeyboard = m_hDllKbdHook
    Exit Function
ErrorHookKeyboard:
    MsgBox Err & ":Error in call to HookKeyboard()." _
    & vbCrLf & vbCrLf & "Error Description: " & Err.Description, vbCritical, "Warning"
    Exit Function
End Function

Public Sub UnHookKeyboard()
    On Error GoTo ErrorUnHookKeyboard
    UnhookWindowsHookEx (m_hDllKbdHook)
    Exit Sub
ErrorUnHookKeyboard:
    MsgBox Err & ":Error in call to UnHookKeyboard()." _
    & vbCrLf & vbCrLf & "Error Description: " & Err.Description, vbCritical, "Warning"
    Exit Sub
End Sub


Public Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Static kbdllhs As KBDLLHOOKSTRUCT
    If nCode = HC_ACTION Then
        Call CopyMemory(kbdllhs, ByVal lParam, Len(kbdllhs))
                If active Then

            MsgBox ("keypressed")
            End If

    End If

我只需要在主窗体中调用HookKeyboard/UnhookKeyboard

,如果我查找一个特定的键,这将起作用,但是当我需要检测任何按键时,这两个键都帮不上忙。我添加了一个查找任何字母键的示例,您可以将其扩展到所有虚拟键代码。这基本上可以检测用户在应用程序外按下的任何键。在我的测试中,我将计时器的时间间隔设置为100毫秒。这对我来说有点问题,因为它有时似乎在没有按下任何键的情况下随机启动,我会发布最终对我有效的代码,但对答案的支持率不高。可能是它捕获了其他一些东西,如鼠标按钮单击或Windows键?在我的例子中,循环从64到90,应该只捕捉A-Z键。也许,我会在调整其他内容以进行检查的同时对其进行另一次测试,我的解决方案已经开始工作,但了解更多并不有害:)