VkKeyScan返回相同的代码,没有用于重音和非重音字母的修饰符

背景:

我正在使用非托管函数SendInput( https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310 ( v= vs.85).aspx)模拟击键。 调用此函数有3种方法:

  1. 指定键盘扫描码
  2. 指定字符unicode
  3. 指定虚拟密钥代码

所有工作,但能够模拟CTRL + PI等快捷方式想要使用虚拟键码。 我目前手动将字符映射到虚拟键码,但这不是一个好方法,因为它对用户的OS键盘布局不敏感。 例如,在英语(英国)键盘上的“。” 字符可以映射到VirtualKeyCode.OEM_PERIOD,但如果操作系统键盘布局是法语,那么“。” 是VirtualKeyCode.OEM_PERIOD + SHIFT。

为了使我的代码更健壮,我想调用方法VkKeyScan( https://msdn.microsoft.com/en-us/library/windows/desktop/ms646329 ( v= vs.85).aspx)传入一个字符到获取虚拟键码(加上shift / ctrl / alt)。 从理论上讲,这种方法可以解决所有问题。

问题:

宣言:

[DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern short VkKeyScan(char ch); 

用法:

 var vkKeyScanResult = PInvoke.VkKeyScan(character); var vk = vkKeyScanResult & 0xff; var shift = (vkKeyScanResult >> 8 & 1) == 1; var ctrl = (vkKeyScanResult >> 8 & 2) == 1; var alt = (vkKeyScanResult >> 8 & 4) == 1; if (vk != -1) { Log.InfoFormat("'{0}' => virtual key code {1}{2}{3}{4}", character, vk, shift ? "+shift" : null, ctrl ? "+ctrl" : null, alt ? "+alt" : null); } 

使用英语(英国)的OS键盘布局,我看到以下结果:

  • ‘e’=>虚拟密钥代码69
  • ‘E’=>虚拟键码69 + shift
  • ‘é’=>虚拟键码69

NB 69在HEX中为0x45,对应于虚拟键码列表中的“E”键,例如http://www.kbdedit.com/manual/low_level_vk_list.html

‘e’和’é’如何产生相同的虚拟密钥代码? 通过按’e’+ ctrl + alt或’e’+ altgr输出英语(英国)键盘上的’é’。

理论:

  1. 我的代码是错误的,我没有正确提取ctrl和alt位。
  2. VkScanKey不能像我期望的那样工作,并且无法将’é’返回’e’+ ctrl + alt(尽管MSDN文档表明它可以)。
  3. 还有别的。

它看起来像理论1 – 我没有正确地提取修改器位。 此代码有效:

 var vkKeyScan = PInvoke.VkKeyScan(character); var vkCode = vkKeyScan & 0xff; var shift = (vkKeyScan & 0x100) > 0; var ctrl = (vkKeyScan & 0x200) > 0; var alt = (vkKeyScan & 0x400) > 0; 

所以问题是要么与操作员排序有关(即&可能优先于>>(位移)),虽然我不这么认为,因为我尝试使用括号位移左右括号,或者这种转变本身没​​有按预期发挥作用。

如果您有兴趣,这是提交工作代码: https : //github.com/JuliusSweetland/OptiKey/commit/0e61c52371638c61e0ef05834cd31a363181ea0d