我正在做一个工作项目,我有点难过。我们有一个图形显示屏,当按下小键盘上的+
或等号键上方的+
时,它会处理键盘输入并放大显示。它适用于大多数计算机,但在瑞士(德国)布局上,+
键是Shift+1
。我们目前正在使用OnKeyDown
,它返回按下的键值(如果我试图处理瑞士+
,则键值为49)以及指示是否按下shift,control和alt键的布尔变量。我已经看过使用OnKeyPress,但我似乎无法检查是否按下了Control键。
我可能在how to capture the '#' character on different locale keyboards in WPF/C#?有一个潜在的解决方案,但是无论键盘设置的语言是什么,都可以使用外部DLL来正确本地化键盘以使用+
键,这看起来非常不优雅。我想相信,自2012年以来,微软已经添加了C#语言的原生内容,以便在外部布局中处理键盘输入,而不会跳过箍。
更糟糕的是,我总能检测到正在使用哪种键盘布局并将其作为一种特殊情况处理,但这似乎是最后的事情。
Keyboard Mapping in .NET处的代码稍微有点用,但它有一些脆弱的位,比如在Keys.Shift
而不是{{1}时访问其边界之外的数组它仍然需要拉入外部DLL。这真的是微软认为不重要的东西吗?
编辑:我认为我已经使用上面的代码来处理" .NET中的键盘映射"。我通过按shift和键获取所有键访问的正确值。我有点担心我会错过其他一些涉及添加Control或Alt的案例,但它有效。我仍然更喜欢更优雅的解决方案。
进一步修改:Get the char on Control.KeyDown?的技术也适用于给定的控件。
稍后修改 :对。它的功能应该如此,但看起来我的错误总是更简单。非小键盘"加"无论按什么按钮触发KeyCode,都应始终映射到Keys.ShiftKey
以获取KeyCode。它不适用于瑞士键盘以及我可能尚未找到的其他键盘。有趣。我不知道我会在哪里举报。
答案 0 :(得分:0)
最终,我选择了How to convert a virtual-key code to a character according to the current keyboard layout?处的代码。我仍然认为这应该更容易构建到代码中,但它现在应该足够了。
[DllImport("user32.dll")]
public static extern int ToUnicode(
uint wVirtKey,
uint wScanCode,
byte[] lpKeyState,
[Out, MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 4)]
StringBuilder pwszBuff,
int cchBuff,
uint wFlags);
static string GetCharsFromKeys(Keys keys, bool shift, bool altGr)
{
var buf = new StringBuilder(256);
var keyboardState = new byte[256];
if (shift)
keyboardState[(int)Keys.ShiftKey] = 0xff;
if (altGr)
{
keyboardState[(int)Keys.ControlKey] = 0xff;
keyboardState[(int)Keys.Menu] = 0xff;
}
ToUnicode((uint)keys, 0, keyboardState, buf, 256, 0);
return buf.ToString();
}