【问题标题】:How to unfocus from a WebView in UWP如何从 UWP 中的 WebView 中取消焦点
【发布时间】:2021-06-27 07:12:24
【问题描述】:

我正在开发一个 UWP 应用,该应用托管一个在单独进程中运行的 WebView。

var webView = new Windows.UI.Xaml.Controls.WebView(WebViewExecutionMode.SeparateProcess)

这会导致一种行为,即如果 WebView 具有焦点,则包含应用程序无法通过简单地尝试将焦点放在 UI 元素上来自行重新获得焦点。

应用程序支持键盘快捷键,这可能会导致不同的元素获得焦点,但当焦点被 WebView 捕获时,它无法正常工作。目标元素似乎获得了焦点,但似乎进程本身没有被激活(因为真正的焦点位于不同的进程中,我想......)。

我目前正尝试通过协议注册以编程方式激活应用程序,以重新获得焦点。

我在应用清单中添加了一个自定义协议 mycustomprotocol 的声明以及以下激活重载

protected override void OnActivated(IActivatedEventArgs args)
{
    if (eventArgs.Uri.Scheme == "mycustomprotocol")
    { }
}

以下代码调用激活:

var result = await Windows.System.Launcher.LaunchUriAsync(new Uri("mycustomprotocol:"));

似乎只在某些计算机上工作,在其他计算机上(不是在调试应用程序时,仅在未附加执行时)而不是重新获得焦点,应用程序的任务栏图标只是闪烁橙色。

我创建了一个示例项目来显示问题和半工作解决方案here

任何关于这方面的见解都会很棒。

【问题讨论】:

  • 你的意思是当webview捕获焦点时,你不能让这个页面上的其他元素获得焦点,对吧?我用 WebViewExecutionMode.SeparateProcess 创建了 webview,代码运行良好。一开始,我使用 FocusManager.TryFocusAsync() 来聚焦 Webview,然后我可以通过代码或鼠标操作轻松聚焦其他元素。那么您能否详细解释一下这个问题并提供您的代码 sn-p?
  • 我添加了一个示例项目,您可以使用它来查看问题,注意任务栏闪烁只是有时会发生
  • 我已经测试了您的示例,代码运行良好。我还没有看到任务栏闪烁。此外,无论应用程序是否被激活,文本框都会获得焦点。所以你不需要使用 Launcher.LaunchUriAsync() 来激活应用程序。
  • 再试一次,按下“安排焦点计时器”按钮,然后将焦点设置在 webview 内,例如 bing 的搜索栏。然后在 3 秒后你会看到焦点移动到目标上,但是这个过程没有焦点,所以如果你尝试在键盘上输入一些东西,你仍然会看到 webview 有真正的焦点。对另一个按钮执行相同操作,您会看到它已解决。正如我所说,闪烁只发生在某些计算机上,它非常不可预测。

标签: webview uwp


【解决方案1】:

我可以重现您的问题。我发现当我们用鼠标切换焦点时,焦点可以转移到TextBlock上。所以你可以通过模拟鼠标输入来解决这个问题。

请使用以下代码代替FocusTarget.Focus(FocusState.Programmatic)

如下:

                    InputInjector inputInjector = InputInjector.TryCreate();

                    var infoDown = new InjectedInputMouseInfo();

                  // adjust your mouse position to the textbox through changing infoDown.DeltaX,infoDown.DeltaY

                    infoDown.DeltaX = 10;   //change

                    infoDown.DeltaY = -150; //change

                    infoDown.MouseOptions = InjectedInputMouseOptions.LeftDown;

                    var infoUp = new InjectedInputMouseInfo();

                    infoUp.DeltaX = 0;

                    infoUp.DeltaY = 0;

                    infoUp.MouseOptions = InjectedInputMouseOptions.LeftUp;

                    inputInjector.InjectMouseInput(new[] { infoDown, infoUp });

注意:如果您使用输入注入 API,您需要在 Package.appxmanifest 中添加 inputInjectionBrokered Capabilitiy。 但是这个能力是受限能力,你不能在商店里发布这个应用,不能通过验证。

【讨论】:

  • 谢谢,但是应用需要通过商店验证,所以不能使用受限功能...
  • 源自官方文档,如果您的应用声明了任何受限功能,您必须在app submission process 期间提供信息,才能获准将应用发布到Microsoft Store。您在提交的Submission options 页面上提供此信息,说明您的应用如何使用它声明的每个受限功能。
  • 此外,如果您使用 SameThread 创建 webview,则不会发生此问题。或者你可以取消三秒延迟操作,点击按钮后立即改变焦点,也可以。
  • True re SameThread(以及SeparateThread)但这也是不可能的,因为应用程序是一个实际的浏览器并且需要能够稳定地处理多个视图。延迟只是为了让测试人员在调用实际焦点之前在 webview 中设置焦点。实际上有一个 JS 脚本注入到视图中,它捕获并转发键盘命令
  • 我们正在就您的问题咨询其他工程师。可能会有一些延迟。
【解决方案2】:

我一直在与一位 WebView 软件工程师进行讨论。问题是,如果您尝试将焦点从 web 视图中移开,那么单独的进程仍然想要拥有焦点。他的解决方案是通过以下调用要求其他进程的 Web 引擎放弃焦点:

_= webView.InvokeScriptAsync("eval", new string[] { "window.departFocus('up', { originLeft: 0, originTop: 0, originWidth: 0, originHeight: 0 });" });

您可以在尝试将焦点更改为目标之前调用它。我进行了各种测试,结果始终如一。

【讨论】:

    猜你喜欢
    • 2016-08-05
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    相关资源
    最近更新 更多