【发布时间】:2018-06-30 04:06:29
【问题描述】:
编辑 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'会通过,但不会通过'e'。它与硬件无关,它只在我正在开发的 UWP 应用程序中执行此操作。
在调试器中,我已经确认这种不需要的行为都是在事件触发之前发生的。当我输入“e”时,args.VirtualKey 正在触发一个“d”。
keyup 事件也只有 95% 的时间才会触发。 CoreWindow.PointerWheelChanged 没有出现这个问题。使用与键盘相同的处理程序的游戏手柄输入也不存在此问题。
UI 线程上的活动越多似乎会增加问题的严重性。
有谁知道如何解决这种情况?任何一种解决方法或替代解决方案,或者至少是对可能发生的情况的解释?
编辑: 我尝试为 Window.Current.CoreWindow.Dispatcher.ProcessEvents() 设置所有 4 个选项,但没有任何改进。
编辑 2: 似乎我正在为全局事件捕获 CoreWindow.Keydown 的事实是不合理的。任何焦点控件上的任何常规 KeyDown 事件也会发生此问题。
编辑 3: 我相信我意识到发生了什么,我认为这是一个错误。我粗略的理解是 UWP 键盘输入被沙盒化以防止键盘记录器恶意软件或其他东西,因此在原始键输入和 CoreWindow 处理的 VirtualKey 之间存在一些较低级别的转换。没关系,但它似乎在某些条件下无法正常工作。
在快速键盘输入(如打字)期间 UI 线程有负载时,它有时不会检测到按键释放。这就是为什么 KeyUp 不会像我提到的那样偶尔触发的原因。这也使 KeyDown 混乱,因为键处于锁定状态,它认为键被按下,而实际上并非如此。然后,当下一个键释放确实注册时,CoreWindow 调度程序刷新其队列,结果是它为前一个键输入和新键输入触发一个事件。所以键入'abcd' 并且'd 不会触发。等待 10 秒钟,然后按“e”。突然,“d”和“e”都会出现。或者更可能再次按'd',因为它没有第一次注册,并且会显示双'dd'。以任何标准衡量都是绝对不可接受的行为。
您可以尝试自己重现它的最佳方法是使用 AutoSuggestBox,它会执行诸如查询之类的阻塞操作,并在您键入时在结果中加载图像缩略图。请记住,即使是一点点的 UI 负载似乎也会导致它。即使我将图像异步预加载为流或字节数组,它仍然会在设置 BitmapImage 源时阻塞 UI 线程 1-2ms。比一帧视频少 1-2 毫秒,因此视觉上难以察觉,但似乎偶尔无法检测到何时释放键盘键就足够了。
这可能是特定于硬件的。我测试过不同的键盘,但没有测试过不同的电脑。
【问题讨论】:
-
我不确定你是否会通过 UWP 应用获得你想要的东西。 UWP 适用于任何 Windows 10 平台;您可以注册到本机桌面 .NET 库,即使您让它工作了,您将如何通过这个来完成应用程序挂起/恢复/后台任务?只是一种预感告诉我,这不能按照您想要的方式完成,您需要编写一个标准的 Windows 应用程序来完成它。您仍然可以将应用程序放入应用程序商店,但仅限 PC。我会监控这个,以防我错了;祝你好运。
-
您的意思是回复其他问题吗?我遇到了 CoreWindow.KeyDown 无法正确触发的问题。我的项目已经开发了 18 个月,它是一个由 UWP、WPF 和 Web 应用程序组成的套件。我对 UWP 应用暂停或恢复没有任何问题。
-
顺便说一句,再次感谢您向我展示如何从依赖属性更新运行代码。
-
大声笑,不。我打算在这里回应,但也许我的评论太罗嗦了,没有意义。我想说的是,我不确定 UWP 应用程序是否完全能够始终如一地捕获来自其他应用程序的击键。我可能是错的,因为我从来没有挖过那么远,但我已经用 WPF (tripleg-3.com) 做到了这一点,并且非常成功(很多年前)。并为混乱道歉;也许我是最困惑的人,这会让我的 cmets 变得奇怪。