如何在Visual Studio中获取死键输入的原始按键码而非合并字符
Visual Studio获取死键原始按键码实现方案
默认你拿到的是合并后字符编码,是因为Visual Studio编辑器默认处理的是系统完成死键组合后的WM_CHAR消息,只会返回最终合成字符的编码。要获取独立的原始按键码、同时区分特殊按键,需要捕获更底层的键盘事件,具体方案如下:
场景1:开发VS扩展,需要内置捕获原始输入
- 优先使用VS SDK提供的
IOleCommandTarget接口挂钩编辑器命令路由:
在扩展初始化逻辑中获取当前文本视图的IVsTextView实例,调用AddCommandFilter方法注册自定义命令过滤器,在Exec方法中可以直接获取到输入被输入法/键盘布局处理前的原始虚拟键码,死键按下、后续普通按键按下会分别独立触发事件,不会被合并。
常见按键对应虚拟键码:反引号(`)对应值96,e对应值101,backspace对应值8,linefeed对应值10,可直接通过数值区分特殊按键。 - 如需更底层捕获,可直接挂钩VS进程的窗口消息,处理
WM_KEYDOWN/WM_SYSKEYDOWN消息,消息的wParam参数即为原始虚拟键码,所有按键事件独立触发,完全不会触发死键合并逻辑。
场景2:仅需要在使用VS时查看自己输入的原始按键码
你可以自行实现一个轻量的键盘监听程序,仅挂钩VS窗口的线程键盘事件,实时输出按键码即可,核心示例代码如下:
// 导入Win32 API [DllImport("user32.dll")] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [DllImport("user32.dll")] static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll")] static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); private const int WH_KEYBOARD = 2; private const int WM_KEYDOWN = 0x0100; private IntPtr _hookId = IntPtr.Zero; // 初始化钩子,仅监听VS主窗口线程 void InitHook() { IntPtr vsMainWindow = FindWindow("VisualStudioMainWindow", null); uint vsThreadId = GetWindowThreadProcessId(vsMainWindow, out _); _hookId = SetWindowsHookEx(WH_KEYBOARD, KeyboardCallback, IntPtr.Zero, vsThreadId); } // 按键回调处理 private IntPtr KeyboardCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { int rawKeyCode = Marshal.ReadInt32(lParam); // 此处可输出或存储原始按键码 Console.WriteLine($"原始按键码:{rawKeyCode}"); } return CallNextHookEx(_hookId, nCode, wParam, lParam); }
注意:不要使用
KeyPress类的托管事件做捕获,这类事件底层基于WM_CHAR消息,已经经过死键组合处理,只能拿到合并后的字符编码。
内容的提问来源于stack exchange,提问作者user3443063
相关产品推荐
相关产品推荐

