【发布时间】:2015-11-04 13:23:57
【问题描述】:
背景:
我正在使用非托管函数 SendInput (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx) 模拟击键。该函数有3种调用方式:
- 指定键盘扫描码
- 指定一个字符 unicode
- 指定虚拟键码
一切正常,但为了能够模拟 CTRL+P 等快捷键,我想使用虚拟键代码。我目前手动将字符映射到虚拟键代码,但这不是一个好方法,因为它对用户的操作系统键盘布局不敏感。例如,在英语(英国)键盘上的“。”字符可以映射到 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);
}
使用英语(英国)的操作系统键盘布局,我看到以下结果:
- 'e' => 虚拟键码 69
- 'E' => 虚拟键码 69+shift
- 'é' => 虚拟键码 69
注意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 文档表明它可以)。
- 别的东西。
【问题讨论】:
-
这是一个不完善的函数,它支持的唯一修饰符是 Shift、Ctrl 和 Alt。不是 AltGr。或者就此而言,使用 IME 输入的任何内容。
-
我已经阅读了一些关于它的限制,但 AltGr 似乎被支持为 Shift+Ctrl。来自 MSDN 文章“对于使用右手 ALT 键作为 shift 键的键盘布局(例如法语键盘布局),shift 状态由值 6 表示,因为右手 ALT 键是在内部转换的进入 CTRL+ALT。”
标签: c# globalization sendinput