查看pdf时隐藏或修改Webview2的工具栏

Posted

技术标签:

【中文标题】查看pdf时隐藏或修改Webview2的工具栏【英文标题】:Hide or modify the toolbar of Webview2 when viewing pdf 【发布时间】:2021-05-18 10:41:04 【问题描述】:

我正在使用新的 Webview2 控件在我的 WPF 应用程序中呈现 Pdf 文件。

这很好,但我想自定义工具栏以隐藏某些条件下的保存按钮。我没有直接从 Webview2/CoreWebView2 对象中找到方法或属性。

但是,如果我检查呈现 pdf 时生成的网页代码,我可以看到保存按钮所在的部分

是否可以在呈现之前截取整个页面并更改 html ?我知道这样做很脏,因为它需要查找可能会更改的类 ID,但它现在可以作为临时解决方案。

【问题讨论】:

【参考方案1】:

是的,可以 100% 将脚本添加到您的环境中,这些脚本可以拦截和控制您正在呈现的内容。

我在 windows 窗体中使用 WebView2,所以我将向您展示我是如何在桌面 windows 窗体应用程序中执行此操作的,该过程对于其他环境将类似,并且对于 WPF 项目几乎相同。

步骤 1

设置和初始化 webview2 控件的默认设置

public FrmMainForm()

  InitializeComponent();

  // Resize/position client to a standard 720p HD TV and make room for tools
  var toolBarSize =
    PnlToolPanelTopRow.Height +
    PnlToolPanelLowerRow.Height;

  SetClientSizeCore(1280, toolBarSize + 720);
  //webview.Top = toolBarSize;
  webview.Height = 720;

  // Webview initialisation handler, called when control instatiated and ready
  webview.CoreWebView2InitializationCompleted += Webview_CoreWebView2InitializationCompleted;

  // Set defaults for tools
  TxtAppUrl.Text = "http://app/";
  TxtUserAgent.Text = DEFAULTUA;

注意初始化完成事件附带的“初始化处理程序”。

第二步

在您的初始化事件处理程序中,您需要在每次初始化浏览器视图时加载您希望运行的 javascript。这些脚本总是在加载页面中的任何脚本之前执行,或者在 dom 加载之前执行,但是它们在页面导航之后执行,因此您不能使用它们来控制导航周期。

这是一个例子,来自我的一个项目

private void Webview_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)

  // Custom URL handler (All URLS starting "http://app/" are intercepted directly by the application
  webview.CoreWebView2.AddWebResourceRequestedFilter("http://app/*", CoreWebView2WebResourceContext.All);
  webview.CoreWebView2.WebResourceRequested += WebResourceRequested;

  // Load in our custom JS API files to create the HbbTv JS environment
  webview.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(JsLoader.LoadApi("BrowserOverrides.js"));

  // Assign any back end C sharp classes to support our JS api's
  webview.CoreWebView2.AddHostObjectToScript("channelData", new ChannelData());

  // Event handler for notification of dom content load finished
  //webview.CoreWebView2.DOMContentLoaded += CoreWebView2_DOMContentLoaded;

  // Show dev tools by default
  webview.CoreWebView2.OpenDevToolsWindow();

  // Other misc settings
  webview.CoreWebView2.Settings.UserAgent = DEFAULTUA;


你需要注意的那一行是这样的:

webview.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(JsLoader.LoadApi("BrowserOverrides.js"));

我使用一个自定义加载器类,它从编译到我的应用程序中的资源中获取我的 java 脚本文件,但是您不需要,传递给 AddScript 调用的唯一参数只是一个普通的 java 字符串脚本代码,例如:

webview.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("alert('hello world');");

将导致您的 webview2 会话在每次导航之后,但在页面中的 dom 和脚本加载并运行之前,对于在 webview 中浏览到的每个页面显示警报。

JS 代码可以完全访问浏览器环境,因此只需将常规 JS 处理程序附加到“dom 加载”或“页面加载”常规 java 脚本事件之一,然后使用标准 dom 操作来查找您想要的元素并将其显示样式设置为“无”。

第 3 步(可选)

您还将从我的第二个代码 sn-p 中看到,还有 2 个可以使用的挂钩点。

webview.CoreWebView2.AddHostObjectToScript("channelData", new ChannelData());

将我的自定义 C# 类类型“ChannelData”添加到浏览器环境中,然后通过以下 JS 代码将其提供给浏览器

chrome.webview.hostObjects.channelData.(method name or property name accessible here)

“channelData”名称,在“hostObjects”之后与“AddHostObject”调用的第一个参数中使用的相同,第二个消息是一个必须设置如下的常规C#类:

using HbbTvBrowser.DataClasses;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

namespace JsSupportClasses

  [ClassInterface(ClassInterfaceType.AutoDual)]
  [ComVisible(true)]
  public class (Class Name Here)
  
    public string SomeMethod()
    
      return JsonConvert.SerializeObject(Some C# objects to return);
    
  

如果没有提供类接口和com可见属性,则该类将不会被Web视图看到并且不可调用。

你的方法返回给 JS 代码的任何数据,必须是简单的数据类型,例如 int、bool 或 string,这意味着你不能返回复杂的对象而不先序列化它们,然后在你返回后反序列化它们JS土地。

您会注意到还有一个 C# 级别的 dom 就绪处理程序。一旦 HTML 被加载并准备好被访问,但在图像、脚本、css 或其他类似的东西被加载之前,它就会被触发。但是,您不能从 C# 更改 dom 内容,至少目前不能,我相信今年某个时候它可能会出现在团队的雷达上,但我无法确认。

虽然我自己不需要这样做,但我确实相信可以在 C# 中获取已加载 HTML 的副本,但这只是“副本”,更改它不会更改实际加载 dom。

【讨论】:

我试着像你提议的那样放置一些脚本并且 JS 正在运行(我有警报),但是如果我尝试通过执行以下脚本来获取页面的内容 await webView.ExecuteScriptAsync("document.body.innerHTML"); 我总是得到一些像"\u003Cembed name=\"EC1D17810B3C396428F857C146BE0D15\" style=\"position:absolute; left: 0; top: 0;\" width=\"100%\" height=\"100%\" src=\"about:blank\" type=\"application/pdf\" internalid=\"EC1D17810B3C396428F857C146BE0D15\">" 这样的内容,这不是我所期望的。我尝试了每一个事件,但也许像这样的 javascript 无法正常工作 我很困惑,为什么您要尝试将主 HTML 文档的内容作为脚本执行? “document.body.innerHTML”不太可能是可运行的 JavaScript,您需要做的是注入您制作的脚本,然后调用该脚本,您制作的脚本应该使用标准 JavaScript 代码与您所在的 DOM 节点进行交互感兴趣,所以你可以操纵它们。 不幸的是,此答​​案中的技术在使用 pdf 时不起作用,因为 pdf 是在单独的 html 文档中显示的<embed>。如果您导航到 pdf 并致电 webview.CoreWebView2.OpenDevToolsWindow(),您可以看到这一点。那里显示的 html 将与使用右键单击 -> 检查时显示的不同。 webview2 javascript 注入作用于错误的 html 文档。

以上是关于查看pdf时隐藏或修改Webview2的工具栏的主要内容,如果未能解决你的问题,请参考以下文章

WebView2 控件不在工具箱中

怎么用adobe acrobat编辑pdf文件

在默认 PDF 查看器的 iframe 中禁用/隐藏下载按钮

PDF文字怎样编辑 如何修改PDF文档

使用pdfFactory隐藏文档中的隐私信息

用PDF编辑器怎样修改PDF文件内容