默认菜单:
WebView2本身携带了类似Edge的右键菜单,但有的时候我们需要对它进行一些修改。
禁止dev菜单
webView.CoreWebView2.Settings.AreDevToolsEnabled = false;
禁止所有菜单
webView.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
自定义菜单
自定义菜单我最初预想的实现的方式是:
-
屏蔽webview2本身的右键菜单
-
定义WPF控件的右键菜单
-
根据右键点击的位置获取WebView上下文信息,显示相应的菜单
然而,实现的时候遇到了一些麻烦:WPF的WebView2是吃掉了所有的鼠标右键事件的,根本无法显示WPF控件自定义的右键菜单,后来查阅了一下相关文章,一般实现的方式如下:
1. 首先定义脚本文档menu.js,该脚本的功能为:订阅右键菜单事件contextmenu,将位置信息发送给host程序,同时屏蔽本身的右键菜单。
document.addEventListener('contextmenu', function (event) {
let para =
{
Key: 'contextmenu',
Pos:
{
X: event.x,
Y: event.y,
}
};
event.preventDefault();
window.chrome.webview.postMessage(para);
});
2. Host程序在前端注入该js,并在接收到位置信息的时候显示自定义的右键菜单。
var script = await File.ReadAllTextAsync(@"menu.js");
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(script);
webView.WebMessageReceived += (s, e) =>
{
var pos = JObject.Parse(e.WebMessageAsJson)["Pos"];
menu.PlacementTarget = webView;
menu.IsOpen = true;
menu.Placement = PlacementMode.Relative;
menu.HorizontalOffset = pos["X"].Value<double>();
menu.VerticalOffset = pos["Y"].Value<double>();
};
做到这一步时,已经可以在WPF程序中显示自己的右键菜单了。需要注意的是这里的contextmenu的显示方法。
实际应用场景中,往往需要根据上下文动态显示不同的菜单,这个就需要我们在contextmenu回调函数中传入更多的信息了,event参数是一个MouseEvent类型的对象,它本身就有不少属性可以直接传出来供我们使用。也可以通过document.elementFromPoint等js函数计算出上下文信息回传回来。
这里的关键点是contextmenu的上下文消息传递,我们也可以使用AddHostObjectToScript的方式嵌入回调函数代替webmessage的,再前端直接调用host程序的显示菜单的函数,实现起来可能更简单些。