VkKeyScan返回相同的代码,没有用于重音和非重音字母的修饰符
背景:
我正在使用非托管函数SendInput( https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310 ( v= vs.85).aspx)模拟击键。 调用此函数有3种方法:
- 指定键盘扫描码
- 指定字符unicode
- 指定虚拟密钥代码
所有工作,但能够模拟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输出英语(英国)键盘上的’é’。
理论:
- 我的代码是错误的,我没有正确提取ctrl和alt位。
- VkScanKey不能像我期望的那样工作,并且无法将’é’返回’e’+ ctrl + alt(尽管MSDN文档表明它可以)。
- 还有别的。
它看起来像理论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