繁体   English   中英

当 WebView 在 C++/XAML/UWP 应用程序中可见时,如何获得键盘输入?

[英]How can I get keyboard input when WebView visible in C++/XAML/UWP App?

我有一个在 Canvas 上呈现的游戏应用程序,其界面呈现在 WebView 中。

所有的赛前菜单都出现在 WebView 中。 当游戏开始时,我将 WebView 切换到具有透明背景的页面,以便您可以通过它看到游戏 Canvas,但我仍然可以覆盖一些界面元素。

这一切都以图形方式运行良好,我可以通过覆盖的 WebView 界面清楚地看到我的游戏。 我可以很愉快地在游戏和界面之间进行交流。

我遇到的问题是让 WebView 放弃键盘,所以我可以使用按键来控制游戏。

我的键盘侦听器是在(理论上)全局事件 Window.Current.CoreWindow.KeyDown 上触发的,因此它应该获取具有焦点的键盘事件。

  • 我无法在 Canvas 上设置焦点(并将 KeyDown 添加到 Canvas),因为它没有 Focus() 方法。
  • 我无法通过调用 Focus(unfocus) 来让 WebView 放弃键盘。 它只是没有。
  • 我无法将 KeyDown 和 KeyUp 处理程序添加到 Webview,并将它们传递给 Canvas,因为 WebView 不支持这些方法。 (参见https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/web-view
  • 我无法将 KeyDown 和 KeyUp 处理程序添加到 WebView 和 Canvas 的公共父级,因为 WebView 不会让事件“冒泡”。
  • 我无法在 Windows 中从游戏中调用低级键盘函数,因为函数调用永远不会返回。 (请参阅如何在 UWP DirectX/XAML 应用程序中调用 GetAsyncKeyState()?
  • 我无法使用 HTML 函数通过 JS 提供输入,因为它们对游戏的响应太慢。
  • 我不能使用 FocusManager 循环浏览可聚焦对象,因为它只选择 WebView。
  • 我不能使用 WebViewBrush,因为覆盖元素需要动画。

如果我隐藏 WebView 一切正常,键盘事件被拾取并且游戏是可控的。 显然,虽然我看不到重叠的元素。

有什么方法可以让我在 WebView 可见时接收键盘事件?

这是一个用 XAML/C++ 编写的 Win 10/UWP 应用程序。 目标平台为 Win 10 10.0.14393.0/ 最低 10.0.10586.0 在运行 Windows 10 v1703 15063.674 的 Surface Book 上测试

可以通过隐藏然后立即再次显示来释放 WebView 的焦点。

webView->Visibility = Visibility::Collapsed;
webView->Visibility = Visibility::Visible;

即使焦点无处可去 - 在此操作之后, FocusManager::GetFocusedElement()将返回 null。

webview 将保持可见,但现在可以通过Window.Current.CoreWindow.KeyDown接收键盘事件。

但是请注意,与 webview 的任何交互(例如触摸、导航)都会使其重新获得焦点,并且您将停止接收键盘事件。

这不是一个非常令人满意的解决方案,但它在某种程度上满足了查看 webview 和接收键盘事件的要求。

有一个类似的问题,但根据安迪的回答设法用这个技巧解决了它:

DispatcherTimer timer = new DispatcherTimer
{
    Interval = TimeSpan.FromMilliseconds(100)
};

timer.Tick += (s, e) =>
{
    if (FocusManager.GetFocusedElement() is WebView webView)
    {
        webView.Visibility = Visibility.Collapsed;
        webView.Visibility = Visibility.Visible;
    }
};

timer.Start();

我们有一个 Webview,它必须始终在我们的游戏中进行交互。 到目前为止,我发现的最不丑陋的解决方法是将全局事件侦听器注入 javascript 以挂钩键盘输入,并通过 notify() 将其转发回应用程序

function onKeyDown(ev: KeyboardEvent) {

    let wrapper = { keyDown: ev }
    window['external']['notify'](JSON.stringify(wrapper));
}

function onKeyUp(ev: KeyboardEvent) {

    let wrapper = { keyUp: ev }
    window['external']['notify'](JSON.stringify(wrapper));
}


...

        let options: AddEventListenerOptions = { capture: true, passive:true,once:false } 
        document.addEventListener("keydown", onKeyDown, options);
        document.addEventListener("keyup", onKeyUp, options);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM