查看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的工具栏的主要内容,如果未能解决你的问题,请参考以下文章