You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WindowsHook捕获键盘键时无法显示含左右侧的完整键名问题

问题分析与修复方案

你的问题核心在于GetKeyNameText函数的lParam参数构造错误,没有正确传递键盘钩子结构体中的扩展键标志,导致系统无法区分左右侧的Ctrl/Alt/Shift键。

问题根源

GetKeyNameText要求的lParam参数需要包含关键的位信息:

  • 位16-23:按键的扫描码(scanCode)
  • 位24:扩展键标志,对应KBDLLHOOKSTRUCT中flags字段的LLKHF_EXTENDED位(值为&H1)

你之前的代码仅将scanCode左移16位,未加入扩展键标志。对于依赖该标志区分左右的按键(Left Ctrl/Alt/Shift、Right Ctrl/Alt),系统无法识别具体是左侧还是右侧,只能显示通用名称。而Right Shift能正常显示,是因为它的扫描码本身属于扩展键范畴,无需额外标志也能被识别。

修复代码

修改KeyboardProc函数中构造GetKeyNameText参数的部分,正确整合扩展键标志:

Private Function KeyboardProc(ByVal nCode As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr

    If wParam = WM_KEYDOWN Or wParam = WM_SYSKEYDOWN Then
    
        Dim kbInfo As KBDLLHOOKSTRUCT
        Dim keyText As String
        Dim lpString As String * 255
        Dim gknlParam As Long
        
        CopyMemory kbInfo, ByVal lParam, LenB(kbInfo)

        ' 正确构造GetKeyNameText的lParam参数
        gknlParam = kbInfo.scanCode * &H10000
        ' 检查扩展键标志,若存在则设置位24
        If (kbInfo.flags And &H1) <> 0 Then
            gknlParam = gknlParam Or &H1000000
        End If
        
        If GetKeyNameText(gknlParam, lpString, 255) > 0 Then
            ' 截断字符串到第一个空字符,避免多余空格
            keyText = "Char/name: " & Left(lpString, InStr(lpString, vbNullChar) - 1)
        End If
        
        MsgBox "ASCII: " & kbInfo.vkCode & vbNewLine & keyText, , "Captured key"
    End If
    
    KeyboardProc = CallNextHookEx(0, nCode, wParam, lParam)
    
End Function

额外优化

原代码中lpString是固定长度字符串,直接输出会包含大量空字符,加入Left(lpString, InStr(lpString, vbNullChar) - 1)可截断到有效内容,让显示更整洁。

验证效果

修复后,所有左右侧按键都能正确显示完整名称:

  • ASCII: 160 → Char/name: Left Shift
  • ASCII: 162 → Char/name: Left Ctrl
  • ASCII: 164 → Char/name: Left Alt
  • ASCII: 163 → Char/name: Right Ctrl
  • ASCII: 165 → Char/name: Right Alt

内容的提问来源于stack exchange,提问作者Y.S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:43:22