编辑4:似乎只有在通过调试器运行应用程序时才会发生这种情况。所以这不是一个主要问题。
我有很多自定义键盘控件,无论控件有什么焦点,都需要触发很多。所以我在我的MainPage构造函数中使用以下代码:
public MainPage()
{
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
Window.Current.CoreWindow.KeyUp += CoreWindow_KeyUp;
}
public void public async void CoreWindow_KeyDown(CoreWindow sender, KeyEventArgs args)
{
// Handle here
}
但我遇到了最糟糕的问题。每当UI线程上发生事情时,它似乎严重干扰键盘输入。它好像存储了某种积压。
例如,如果我转到AutoSuggestBox,每个按键执行大量逻辑操作,并使用从服务器等加载的图形填充结果,并输入' abcd'它经常是' d'没有注册。然后,当我输入' e'几秒钟后,' d'将会通过,但不是'。它与硬件无关,只能在我正在使用的UWP应用中执行此操作。
在调试器中,我已经确认在事件被触发之前发生了这种不必要的行为。 args.VirtualKey正在解雇一个' d'当我输入' e'
此外,keyup事件仅在95%的时间内触发。 CoreWindow.PointerWheelChanged
没有出现此问题。使用与键盘相同的处理程序的游戏手柄输入也没有这个问题。
UI线程上的活动越多似乎会增加问题的严重性。
有谁知道如何解决这种情况?任何形式的解决方案或替代解决方案,或至少解释可能发生的事情?
编辑: 我尝试为Window.Current.CoreWindow.Dispatcher.ProcessEvents()设置所有4个选项,没有任何改进。
编辑2: 似乎我在全球事件中捕获CoreWindow.Keydown这一事实并非如此。任何聚焦控件上的任何常规KeyDown事件也会发生此问题。
编辑3: 我相信我意识到发生了什么,我认为这是一个错误。我粗略的理解是,UWP键盘输入是沙箱,以防止键盘记录器恶意软件或其他东西,因此在原始键输入和CoreWindow处理的VirtualKey之间有一些较低级别的转换。这很好,但似乎在某些条件下它不能正常工作。
当在快速键盘输入(如输入)期间UI线程上有负载时,它有时不会检测到密钥释放。这就是为什么KeyUp不会像我提到的那样偶尔发射。这也搞砸了KeyDown,因为键处于锁定状态,它认为键被按下,而实际上键不是。然后,当下一个密钥释放注册时,CoreWindow调度程序刷新其队列,结果是它触发前一个键输入和新键输入的事件。所以输入' abcd'并且没有开火。等待10秒钟,然后按“'”。突然间,两个人都在'并且' e'会出现。或者更喜欢按下' d'再次,因为它没有第一次注册,并且双倍'会显示。任何标准都绝对是不可接受的行为。
您可以尝试自己重现它的最佳方法是使用AutoSuggestBox来阻止查询,并在键入时在结果中加载图像缩略图。请记住,即使一小部分UI负载似乎也会导致它。即使我异步地将图像预加载为流或字节数组,当设置BitmapImage源时,它仍然会阻塞UI线程1-2ms。比视频帧少1-2毫秒,因此在视觉上难以察觉,但似乎有时候不会检测到键盘键何时被释放。
这可能是硬件特定的。我测试了不同的键盘但没有测试不同的计算机。
答案 0 :(得分:1)
你可以试试这个:
callback.onResult(it.items, params.key + 1)
您可以将键码用于其他键盘字符。
答案 1 :(得分:0)
快速键盘输入期间UI线程上的活动可防止CoreWindow检测到密钥发布,至少在某些硬件上,目标是1803 Spring Creators Update。希望有人知道更好的解决方案,但现在这是一个 部分 解决方案解决方案:
public void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
CoreVirtualKeyStates keyState = sender.GetAsyncKeyState(args.VirtualKey);
if ((int)keyState == 3)
{
// KeyState is locked and pressed.
// Whenever this happens it means the event fired when I actaually pressed this key.
// Handle event.
}
else if ((int)keyState == 2)
{
// KeyState is locked but not pressed. How if it's not caps lock?
// When this happens it's an unwanted duplicate of the last keystroke.
// Do not handle event.
}
else if ((int)keyState == 0)
{
// Key state is None?!? How can a key that isn't currently down fire a KeyDown event?
// This is a phantom delayed rection of a missed event from two keystrokes ago.
// Do not handle event.
}
}
这可以防止延迟反应问题,但结果仍然会丢失按键。不理想但是有了很大的改进。
这是枚举: https://docs.microsoft.com/en-us/uwp/api/windows.ui.core.corevirtualkeystates
奇怪的状态3(“按下|锁定”)始终代表正确的键输入不在文档中。
另请注意,'CoreVirtualKeyStates == 0'表明这是一个错误,至少在我的硬件上。具有“无”状态的键如何触发KeyDown事件?没有人的手指那么快。我认为这是CoreWindow调度程序刷新其队列,因为它错过了一个KeyUp事件。