如何在WPF中创建反斜杠键的按键绑定?

4
尝试为我们的WPF命令定义一个 CTRL-\(反斜杠)键绑定,但我们遇到了两个问题:
  1. 没有预定义反斜杠键的常量,只有 OemBackslash,而且

  2. OemBackslash 没有一致的数字代码

例如,如果您在戴尔计算机上或在Mac上启动Windows,则 Dell 会返回不同的 e.Key 值。然而,两者都可以正确输入反斜杠。
让我感到沮丧的是,Microsoft 基于按键代码而不是驱动程序中这些代码映射到什么(即键面上实际内容),使得键盘快捷键并不一定一致。
我的想法是,不使用键绑定,而是使用 PreviewKeyDown 事件,然后检查按键代码,以某种方式将其传递给驱动程序以确定所表示的已键入的按键(即该驱动程序会说 keycode X 表示反斜杠键面),然后将该值用于我们的逻辑。但是,我不知道如何从 KeyCode 转换为键面。
所以...您对如何处理/执行此操作有什么想法吗?
1个回答

6

编辑

我强烈建议您不要直接滚动到编辑的结尾,我知道键盘图片非常诱人,但为了更好的体验,请按顺序阅读 :D

就像我说的一样,没有绝对的尝试价值,这种方法是不可靠的,所以你如何期望不可靠的东西能够可靠地工作呢? 甚至为了这个目的去尝试反向工程驱动程序或解密 USB 流都毫无意义,任何理智的人都会告诉你:D

即使你成功实现了其中任何一个(在我看来高度不确定),你也只能针对特定品牌的键盘才行。另一方面还有时间因素,这对结果来说是巨大的浪费。

我在C#中找到的最接近金属的东西是这个:

使用C#从原始输入处理多个键盘

RawInputProcess.RawKeyboard.ProcessRawInput 调用 User32 中的 GetRawInputData。即使是这种低级别的内容也会返回 0xDC 或 220(即可怕的 Oem5)。这将调用 VirtualKeyCorrection,它会纠正一些键,你可以在那里做一些事情,尽管它非常丑陋且不可靠。

此外,还有一堆关于 HID 库的链接 here

我的明确答案:

你绝对想要能够绑定吗?

  • 创建一个表单,允许用户定义快捷方式
  • 按照我在StackOverflow上演示的那样进行丑陋的黑客攻击:D
  • 将此命令的默认快捷键设置为使用Oem5
  • 祈求没有暴力的精神病患者敲门

这样您就会得到Ctrl+\的默认绑定。

现在让我们来了解一些历史和您可能还没有注意到的东西!

如果您仔细查看MSDN文档-> Keys Enumeration

OemBackslash

RT 102键键盘(Windows 2000或更高版本)上的OEM尖括号或反斜杠键。

我很确定您知道这件事,但甚至没有注意到它。

enter image description here

enter image description here

我在1986年的时候,5岁的时候就开始在IBM XT克隆机上亲自玩耍了。

现在你可能已经开始理解了,但我还是想让它更加清晰明了:

OemBackslash 是80年代的遗物,就像Windows中的许多其他东西一样(尽管大多数,如果不是全部,都已在当前版本中被删除)。

所以,除非你有这些键盘之一,否则你将永远不会收到此 KeyCode

我不能百分之百确定,除非有人在2000/XP下使用DIN到PS/2适配器测试RT-102,这将是很有趣的结果;但是让我有信心说这个的原因是,首先是文档,其次是微软的人员通常知道他们在做什么,他们写了那个东西。如果这是错误的,我会吃我的帽子。

我希望您对我的编辑感到满意,并最终哀悼 OemBackslash,我完全理解您想在屏幕上看到这样的东西的愿望,但没有什么是完美的,特别是在计算机领域。我给你提供了一个完全等效的伪解决方案,请尝试一下!

图片的制作者为:


我一直在阅读你之前的问题,就像Hans所说的那样:不要绑定它,因为它不一定是反斜杠。
例如,在法语键盘上,要获取反斜杠,您必须按AltGr8AltGr不过是Alt+Ctrl,这意味着除了按下Alt以外,还需要额外按下Alt以执行您的命令。

http://en.wikipedia.org/wiki/AltGr_key

简而言之,此快捷方式不可靠,因为它根据布局和/或制造商不是恒定的。
在WPF中有KeyInterop.VirtualKeyFromKey,但它也返回Oem5 :(
查看文档可以得到明确的答案:Virtual-Key Codes
VK_OEM_5
0xDC
Used for miscellaneous characters; it can vary by keyboard.
For the US standard keyboard, the '\|' key

但是这里有一个解决方案 :D

按下 \ 将会输入 Oem5,但是通过发送事件到一个 TextBox ,你的系统将会进行所有必要的魔法来将其转换为一个 \。然后你可以获取 TextBox.Text 并根据已输入的键和修饰符采取相应的操作。

enter image description here

private bool _done;
private void MainWindow_OnKeyDown(object sender, KeyEventArgs e)
{
    if (_done) return;
    _done = true;

    var presentationSource = PresentationSource.FromDependencyObject(this);
    var keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, presentationSource, 0, e.Key)
    {
        RoutedEvent = KeyDownEvent
    };
    TextBox1.Focus();
    TextBox1.RaiseEvent(keyEventArgs);
}

private void TextBox1_OnTextChanged(object sender, TextChangedEventArgs e)
{
    var text = TextBox1.Text;
}

注意 1: 这里的boolean是为了防止StackOverflow :D

注意 2: 这可能和按键一样不可靠,如果用户按下Shift键怎么办?我没有尝试过

这只是一个可以实现的概念证明,但个人认为我不会选择这条路,因为它太丑了;我宁愿允许用户将命令映射到他希望的手势。当然,也不允许他绑定到\ :)

编辑

我有一个微软键盘和mskey.exe可以诊断您的键盘:

enter image description here

它确实导入了HID.DLL函数,例如HidP_GetValueCaps,因此您可能可以通过一些P/Invoke以更清晰的方式实现这一点,但这似乎需要很多工作。

1
我给你点赞,因为a)你找到了我的旧帖子(我知道我写过一个但是找不到了!)b)你提供的细节非常详细,c)你展示了那个我不知道的酷炫的<kbd>X</kbd>技巧! :) 如果你最后一条关于PInvoke的评论有效,我会回来标记这个作为答案。 - Mark A. Donohoe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接