c# - VkKeyScan 返回相同的代码,不带重音字母和非重音字母的修饰符

标签 c# globalization sendinput

背景:

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

  1. 指定键盘扫描码
  2. 指定一个字符unicode
  3. 指定一个虚拟键码

一切正常,但为了能够模拟 CTRL+P 等快捷方式,我想使用虚拟键码。我目前有一个字符到虚拟键码的手动映射,但这不是一个好方法,因为它对用户的操作系统键盘布局不敏感。例如,在英语 (UK) 键盘上,“.”字符可以映射到 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 在十六进制中是 0x45,对应于虚拟键码列表中的“E”键,例如 http://www.kbdedit.com/manual/low_level_vk_list.html

“e”和“é”如何产生相同的虚拟键码?英语 (UK) 键盘上的 'é' 通过按 '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

关于c# - VkKeyScan 返回相同的代码,不带重音字母和非重音字母的修饰符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33523071/

相关文章:

c# - 在 C# 中使用英语以外的默认 UI 语言是否可以?

c++ - 无法模拟 Alt-Tab 虚拟按键,与其他键配合正常

keystroke - SendInput 不适用于游戏

c# - 如何使用货币符号将字符串解析为十进制?

unicode - 理解术语——字符编码、字体、字形

c# - SSIS 2008 : Using Custom DLL's in Script Task/Script Components that are versioned

c# - 为什么在 .net 中存在 Equals 的静态和非静态重载?

c# - 多态类型和 IXmlSerializable

c# - 字符串到字节数组