简体   繁体   English

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

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

I have a game app that is rendered on a Canvas, with an interface rendered in a WebView.我有一个在 Canvas 上呈现的游戏应用程序,其界面呈现在 WebView 中。

All the pre-game menus happen in the WebView.所有的赛前菜单都出现在 WebView 中。 When the game starts I switch the WebView to a page with a transparent background so you can see the game Canvas through it, but I can still overlay some interface elements.当游戏开始时,我将 WebView 切换到具有透明背景的页面,以便您可以通过它看到游戏 Canvas,但我仍然可以覆盖一些界面元素。

This all works fine graphically, and I can see my game clearly with the WebView interface overlayed.这一切都以图形方式运行良好,我可以通过覆盖的 WebView 界面清楚地看到我的游戏。 I can communicate between the game and the interface quite happily.我可以很愉快地在游戏和界面之间进行交流。

The problem I have is getting the WebView to give up the keyboard, so I can use the keys to control the game.我遇到的问题是让 WebView 放弃键盘,所以我可以使用按键来控制游戏。

My keyboard listener is triggered on the (theoretically) global event Window.Current.CoreWindow.KeyDown, so it should get keyboard events whatever has the focus.我的键盘侦听器是在(理论上)全局事件 Window.Current.CoreWindow.KeyDown 上触发的,因此它应该获取具有焦点的键盘事件。

  • I cannot set the focus on the Canvas (and add KeyDown to the Canvas), because it doesn't have a Focus() method.我无法在 Canvas 上设置焦点(并将 KeyDown 添加到 Canvas),因为它没有 Focus() 方法。
  • I cannot get the WebView to relinquish the keyboard by calling Focus(unfocus).我无法通过调用 Focus(unfocus) 来让 WebView 放弃键盘。 It just doesn't.它只是没有。
  • I cannot add KeyDown and KeyUp handlers to the Webview, and pass them on to the Canvas, because WebView doesn't support those methods.我无法将 KeyDown 和 KeyUp 处理程序添加到 Webview,并将它们传递给 Canvas,因为 WebView 不支持这些方法。 (see https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/web-view ) (参见https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/web-view
  • I cannot add KeyDown and KeyUp handlers to the common parent of the WebView and Canvas, because the WebView doesn't let the events 'bubble up'.我无法将 KeyDown 和 KeyUp 处理程序添加到 WebView 和 Canvas 的公共父级,因为 WebView 不会让事件“冒泡”。
  • I cannot call the low-level keyboard functions from the game in Windows, because the function calls never return.我无法在 Windows 中从游戏中调用低级键盘函数,因为函数调用永远不会返回。 (See How Can I Call GetAsyncKeyState() in UWP DirectX/XAML App? ) (请参阅如何在 UWP DirectX/XAML 应用程序中调用 GetAsyncKeyState()?
  • I cannot use the HTML functions to provide input via JS, because they're too unresponsive for the game.我无法使用 HTML 函数通过 JS 提供输入,因为它们对游戏的响应太慢。
  • I cannot use FocusManager to cycle through the focussable objects, because it only ever chooses the WebView.我不能使用 FocusManager 循环浏览可聚焦对象,因为它只选择 WebView。
  • I cannot use WebViewBrush because overlay elements need to animate.我不能使用 WebViewBrush,因为覆盖元素需要动画。

If I hide the WebView everything works fine, the keyboard events are picked up and the game is controllable.如果我隐藏 WebView 一切正常,键盘事件被拾取并且游戏是可控的。 Obviously though I can't see the overlayed elements.显然,虽然我看不到重叠的元素。

Is there some way to let me receive the keyboard events when the WebView is visible?有什么方法可以让我在 WebView 可见时接收键盘事件?

This is a Win 10/UWP app written in XAML/C++.这是一个用 XAML/C++ 编写的 Win 10/UWP 应用程序。 Target platform is Win 10 10.0.14393.0/ minimum 10.0.10586.0 Tested on Surface Book running Windows 10 v1703 15063.674目标平台为 Win 10 10.0.14393.0/ 最低 10.0.10586.0 在运行 Windows 10 v1703 15063.674 的 Surface Book 上测试

It is possible to release the focus from the WebView by hiding and then showing it again immediately.可以通过隐藏然后立即再次显示来释放 WebView 的焦点。

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

Even if there's nowhere else for the focus to go - after this operation, FocusManager::GetFocusedElement() will return null.即使焦点无处可去 - 在此操作之后, FocusManager::GetFocusedElement()将返回 null。

The webview will remain visible, but keyboard events can now be received via Window.Current.CoreWindow.KeyDown . webview 将保持可见,但现在可以通过Window.Current.CoreWindow.KeyDown接收键盘事件。

Note however that any interaction with the webview (eg. touch, navigation) will cause it to regain focus and you will stop receiving keyboard events.但是请注意,与 webview 的任何交互(例如触摸、导航)都会使其重新获得焦点,并且您将停止接收键盘事件。

This isn't a very satisfactory solution, but it sort-of fulfills the requirement to see the webview but also receive keyboard events.这不是一个非常令人满意的解决方案,但它在某种程度上满足了查看 webview 和接收键盘事件的要求。

Had a similar problem but managed to fix it with this trick based on Andy's answer:有一个类似的问题,但根据安迪的回答设法用这个技巧解决了它:

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

We have a Webview that must be interactive in our game at all times.我们有一个 Webview,它必须始终在我们的游戏中进行交互。 The least ugly workaround that I have found so far is injecting a global event listener into the javascript to hook keyboard input, and relaying this back to the app via notify()到目前为止,我发现的最不丑陋的解决方法是将全局事件侦听器注入 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