当在C ++ / XAML / UWP App中看到WebView时,如何获得键盘输入?

时间:2017-10-10 21:20:02

标签: c++ xaml canvas webview uwp

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

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

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

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

我的键盘侦听器是在(理论上)全局事件Window.Current.CoreWindow.KeyDown上触发的,因此无论焦点是什么,都应该获得键盘事件。

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

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

当WebView可见时,有没有办法让我接收键盘事件?

这是一个用XAML / C ++编写的Win 10 / UWP应用程序。 目标平台是Win 10 10.0.14393.0/ minimum 10.0.10586.0 在运行Windows 10 v1703 15063.674

的Surface Book上测试

3 个答案:

答案 0 :(得分:1)

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

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

即使没有其他地方可以关注 - 在此操作之后,FocusManager::GetFocusedElement()将返回null。

网页视图仍然可见,但现在可以通过Window.Current.CoreWindow.KeyDown接收键盘事件。

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

这不是一个非常令人满意的解决方案,但它可以满足查看webview但同时接收键盘事件的要求。

答案 1 :(得分:0)

遇到了类似的问题,但是根据安迪的答案设法解决了这个问题。

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();

答案 2 :(得分:0)

我们拥有一个Webview,该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);