8

我已经看到了许多建议使用Keyboard.Modifiers来确定KeyDown事件是否针对具有修饰符集的键的答案。不幸的是,因为Keyboard.Modifiers返回修饰符的当前状态(而不是按下键时修饰符的状态),这会导致快速打字员非常烦人的间歇性错误。

具体来说,假设有人按下 Ctrl+A,然后在按下 A 几毫秒后松开 Ctrl。现在假设系统负载很重;密钥处理程序开始执行但被抢占了 50 毫秒。当键处理程序再次执行时,Ctrl 的当前状态是“释放”。键处理程序现在会认为在没有 Ctrl 的情况下按下了“A”,这很糟糕

同样,如果快速打字员输入 A,Ctrl+End 并且我的应用程序使用Keyboard.Modifiers,它最终可能会观察到 Ctrl+A...

在 WinForms 中,该事件准确地KeyDown告诉我 Ctrl 的状态,即使在处理事件时它已经被释放。如何在 WPF 中获得相同的行为?

编辑:Keyboard.Modifiers 可能实际上并未检索“当前”修饰键,而是检索与当前正在处理的按键消息相关的修饰键。在 WinAPI 中,这是“异步”和非异步键状态函数之间的区别。不幸的是,文档没有提到“当前”的确切含义。如果有人知道,请说出来。

4

2 回答 2

2

由于事件参数中似乎没有任何修饰符信息,您可以自己跟踪某些字段中的状态并处理两者KeyUpKeyDown相应地更新它们。

例如

private bool ctrl = false;
private void This_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.LeftCtrl) //or switch, also: `LeftCtrl` & `RightCtrl` are treated as separate keys
        ctrl = true;
    //etc..
}

private void This_KeyUp(object sender, KeyEventArgs e)
{
    if (e.Key == Key.LeftCtrl)
        ctrl = false;
    //etc..
}

这是否真的是一个好主意,我不能说......


如果你想处理关键手势,我建议使用专用方法,比如KeyBindings它们应该只在手势发生时触发。对于其他输入,您可能还想看看TextInput哪个更抽象,并返回输入被翻译成的文本。

于 2012-08-25T21:53:14.870 回答
2

对不起这个破坏性的答案,但......

经过一点研究,我很清楚......该事件被称为“KeyDown”而不是“KeyCombinationDown”,因此它完全独立于之前按下的任何修饰符......

实际上,有一个正确的方法可以实现您的目标:使用命令模式。

您定义一个命令(参见 google 的 WPF 命令)并向您的应用程序添加一个 KeyBinding,您可以在其中定义将启动命令的键或键/键组合...

请参阅此处的示例:http: //msdn.microsoft.com/en-us/library/system.windows.input.keybinding.aspx

恕我直言,这是唯一的方法,并且在语义上也更优雅。

(如果此模式在 GENERAL 中对您不起作用,您可能必须使用带有 pinvoke 的本机 api)。

干杯。

于 2012-08-26T03:17:27.130 回答