【问题标题】:How do you override the ContextMenu that appears when right clicking on WebView2 Control?如何覆盖右键单击 WebView2 控件时出现的 ContextMenu?
【发布时间】:2020-10-18 19:18:30
【问题描述】:

如何覆盖右键单击 WebView2 控件时出现的 ContextMenu?

当您右键单击 WebView2 控件时,会出现带有“刷新”、“另存为”等选项的标准上下文菜单。

如何让我自己的 ContextMenuStrip 出现,而​​不是在鼠标右键单击期间出现?

【问题讨论】:

    标签: .net webbrowser-control webview2


    【解决方案1】:

    更新(现在代码在右键单击时显示您的上下文菜单,并在您单击任意位置时将其隐藏):

    您可以将以下javascript注入到您的网页中(它订阅了“contextmenu”事件和“mousedown”事件):

    document.addEventListener('contextmenu', function (event)
    {
        let jsonObject =
        {
            Key: 'contextmenu',
            Value:
            {
                X: event.screenX,
                Y: event.screenY
            }
        };
        window.chrome.webview.postMessage(jsonObject);
    });
    
    document.addEventListener('mousedown', function (event)
    {
        let jsonObject =
        {
            Key: 'mousedown',
            Value:
            {
                X: event.screenX,
                Y: event.screenY
            }
        };
        window.chrome.webview.postMessage(jsonObject);
    });
    

    将它保存在文件中是最简单的(我称之为“Javascript1.js”)。

    要使用“CoreWebView2”实例,必须初始化 WebView2 控件,订阅“CoreWebView2InitializationCompleted”可以解决这个问题。

    要注入您的javascript,您可以从文件中加载它并使用AddScriptToExecuteOnDocumentCreatedAsync 注入它。

    您需要禁用默认上下文菜单。这是通过将AreDefaultContextMenusEnabled 属性设置为false 来完成的。

    然后你需要订阅WebMessageReceived事件并处理这两个事件。为此,请创建一个包含“Key”和“Value”的结构来反序列化从 javascript 代码发送的 JSON 字符串。

    C# 代码,显示带有事件的整个表单:

    using Newtonsoft.Json;
    using System;
    using System.Drawing;
    using System.IO;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            struct JsonObject
            {
                public string Key;
                public PointF Value;
            }
    
            private async void WebView21_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
            {
                webView21.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
                string script = File.ReadAllText(Path.Combine(Environment.CurrentDirectory, @"Javascript1.js"));
                await webView21.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(script);
            }
    
            private void WebView21_WebMessageReceived(object sender, Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs e)
            {
                JsonObject jsonObject = JsonConvert.DeserializeObject<JsonObject>(e.WebMessageAsJson);
                switch (jsonObject.Key)
                {
                    case "contextmenu":
                        contextMenuStrip1.Show(Point.Truncate(jsonObject.Value));
                        break;
                    case "mousedown":
                        contextMenuStrip1.Hide();
                        break;
                }
            }
        }
    }
    

    【讨论】:

    • 这行得通,虽然还需要一些方法来关闭菜单,否则如果你做任何事情,除了选择一个菜单项,它就会停留在那里
    • @GarrGodfrey:我已经更新了答案以包含隐藏上下文菜单的代码。
    • 不错。我还发现我可以在菜单启动时捕获鼠标并直接处理鼠标事件
    • 一个缺点是这个事件首先在每次鼠标点击时解析该 Json。目前我还没有找到解决方法
    • @Dave:鼠标点击不需要太多电脑,json解析也不需要,所以不用担心性能。顺便说一句,我刚刚将代码更改为使用CoreWebView2InitializationCompletedevent 并等待AddScriptToExecuteOnDocumentCreatedAsync
    【解决方案2】:

    我们还没有完全支持自定义上下文菜单,但是我们有a feature request tracking it。在此期间,您可以使用the work around described in that feature request issue 解决此问题。

    基本上,解决方法是使用 document.body 的 contextmenu 事件来拦截通常的上下文菜单处理并实现您自己的。您可以使用window.chrome.webview.postMessage 将上下文菜单事件发送到您的本机代码以创建本机上下文菜单,或者您可以在 HTML/JS 中实现上下文菜单。

    抱歉,这不是一个简单的解决方案。如果您愿意,可以将自己的 cmets 添加到功能请求中,让我们了解您的场景等,以便在 WebView2 中使用上下文菜单。谢谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-16
      • 2022-12-23
      • 2011-07-20
      • 2022-07-12
      • 1970-01-01
      • 2011-11-13
      • 2013-06-18
      相关资源
      最近更新 更多