上下文菜单

本文介绍将如何使用上下文菜单。

默认情况下, IBrowser 实例的上下文菜单是被抑制的。 如果 IBrowserView 实例是从没有自定义上下文菜单处理的 IBrowser 实例初始化的,则会注册默认上下文菜单处理程序。 默认上下文菜单中显示的项目取决于右键单击的网页项目,但是,在大多数情况下,它包含以下项目:”后退”、”前进”、”重新加载”、”打印”和”查看页面源代码”。

默认的上下文菜单实现是不能被修改的。 如果您需要添加或删除一些项目,您应该创建并注册自己的上下文菜单处理程序实现。

自定义上下文菜单

要构建自定义上下文菜单,应使用 IBrowser.ShowContextMenuHandler 处理程序。

WinForms

browser.ShowContextMenuHandler =
    new AsyncHandler<ShowContextMenuParameters, ShowContextMenuResponse
    >(ShowMenu);
browser.ShowContextMenuHandler =
    New AsyncHandler(
        Of ShowContextMenuParameters, ShowContextMenuResponse)(
            AddressOf ShowMenu)
private ToolStripItem BuildMenuItem(string item, bool isEnabled,
                                    EventHandler clickHandler)
{
    ToolStripItem result = new ToolStripMenuItem
    {
        Text = item,
        Enabled = isEnabled
    };
    result.Click += clickHandler;

    return result;
}

private Task<ShowContextMenuResponse> ShowMenu(ShowContextMenuParameters parameters)
{
    TaskCompletionSource<ShowContextMenuResponse> tcs =
        new TaskCompletionSource<ShowContextMenuResponse>();

    SpellCheckMenu spellCheckMenu = parameters.SpellCheckMenu;
    if (spellCheckMenu != null)
    {
        BeginInvoke(new Action(() =>
        {
            ContextMenuStrip popupMenu = new ContextMenuStrip();
            if(!string.IsNullOrEmpty(parameters.LinkText))
            {
                ToolStripItem buildMenuItem =
                    BuildMenuItem("Show the URL link", true,
                                  (sender, args) =>
                                  {
                                      string linkURL = parameters.LinkUrl;
                                      Console.WriteLine($"linkURL = {linkURL}");
                                      MessageBox.Show(linkURL, "URL");
                                      tcs.TrySetResult(ShowContextMenuResponse.Close());
                                  });
                popupMenu.Items.Add(buildMenuItem);
            }

            ToolStripItem reloadMenuItem =
                BuildMenuItem("Reload", true, 
                              (sender, args) =>
                              {
                                  Console.WriteLine("Reload current web page");
                                  browser.Navigation.Reload();
                                  tcs.TrySetResult(ShowContextMenuResponse.Close());
                              });
            popupMenu.Items.Add(reloadMenuItem);

            // 当浏览器请求返回焦点时关闭上下文菜单。
            EventHandler<FocusRequestedEventArgs> onFocusRequested = null;
            onFocusRequested = (sender, args) =>
            {
                BeginInvoke((Action) (() => popupMenu.Close()));
                parameters.Browser.FocusRequested -= onFocusRequested;
            };
            parameters.Browser.FocusRequested += onFocusRequested;

            // 处理菜单关闭事件。
            ToolStripDropDownClosedEventHandler menuOnClosed = null;
            menuOnClosed = (sender, args) =>
            {
                bool itemNotClicked =
                    args.CloseReason != ToolStripDropDownCloseReason.ItemClicked;
                if (itemNotClicked)
                {
                    tcs.TrySetResult(ShowContextMenuResponse.Close());
                }

                popupMenu.Closed -= menuOnClosed;
            };
            popupMenu.Closed += menuOnClosed;

            // 显示上下文菜单。
            Point location = new Point(parameters.Location.X, parameters.Location.Y);
            popupMenu.Show(this, location);
            tcs.TrySetResult(ShowContextMenuResponse.Close());
        }));
    }
    else
    {
        tcs.TrySetResult(ShowContextMenuResponse.Close());
    }

    return tcs.Task;
}
Private Function BuildMenuItem(item As String, isEnabled As Boolean,
                               clickHandler As EventHandler) As ToolStripItem
    Dim result As ToolStripItem = New ToolStripMenuItem With {
            .Text = item,
            .Enabled = isEnabled
            }
    AddHandler result.Click, clickHandler

    Return result
End Function

Private Function ShowMenu(parameters As ShowContextMenuParameters) _
    As Task(Of ShowContextMenuResponse)
    Dim tcs As New TaskCompletionSource(Of ShowContextMenuResponse)()
    Dim spellCheckMenu As SpellCheckMenu = parameters.SpellCheckMenu

    If spellCheckMenu IsNot Nothing Then
        BeginInvoke(New Action(Sub()
            Dim popupMenu As New ContextMenuStrip()
            If Not String.IsNullOrEmpty(parameters.LinkText) Then
                Dim menuItem As ToolStripItem =
                    BuildMenuItem("Show the URL link", True, Sub(sender, args)
                        Dim linkURL As String = parameters.LinkUrl
                        Console.WriteLine($"linkURL = {linkURL}")
                        MessageBox.Show(linkURL, "URL")
                        tcs.TrySetResult(ShowContextMenuResponse.Close())
                    End Sub)
                popupMenu.Items.Add(menuItem)
            End If

            Dim reloadMenuItem As ToolStripItem =
                BuildMenuItem("Reload", True, Sub(sender, args)
                    Console.WriteLine("Reload current web page")
                    browser.Navigation.Reload()
                    tcs.TrySetResult(ShowContextMenuResponse.Close())
                End Sub)
            popupMenu.Items.Add(reloadMenuItem)

            ' 当浏览器请求返回焦点时关闭上下文菜单。
            Dim onFocusRequested As EventHandler(Of FocusRequestedEventArgs) = Nothing
            onFocusRequested = Sub(sender, args)
                BeginInvoke(CType(Sub() popupMenu.Close(), Action))
                RemoveHandler parameters.Browser.FocusRequested, onFocusRequested
            End Sub
            AddHandler parameters.Browser.FocusRequested, onFocusRequested

            ' 处理菜单关闭事件。
            Dim menuOnClosed As ToolStripDropDownClosedEventHandler = Nothing
            menuOnClosed = Sub(sender, args)
                Dim itemNotClicked As Boolean = 
                        args.CloseReason <>
                        ToolStripDropDownCloseReason.ItemClicked

                If itemNotClicked Then
                    tcs.TrySetResult(ShowContextMenuResponse.Close())
                End If

                RemoveHandler popupMenu.Closed, menuOnClosed
            End Sub
            AddHandler popupMenu.Closed, menuOnClosed

            ' 显示上下文菜单。
            Dim location As New Point(parameters.Location.X, parameters.Location.Y)
            popupMenu.Show(Me, location)
            tcs.TrySetResult(ShowContextMenuResponse.Close())
        End Sub))
    Else
        tcs.TrySetResult(ShowContextMenuResponse.Close())
    End If

    Return tcs.Task
End Function

我们的存储库中提供了完整的示例: C#, VB.NET

WPF

browser.ShowContextMenuHandler =
    new AsyncHandler<ShowContextMenuParameters, 
                     ShowContextMenuResponse>(ShowContextMenu);
browser.ShowContextMenuHandler =
    New AsyncHandler(Of ShowContextMenuParameters, ShowContextMenuResponse )(
        AddressOf ShowContextMenu)
private Task<ShowContextMenuResponse> ShowContextMenu(
    ShowContextMenuParameters parameters)
{
    TaskCompletionSource<ShowContextMenuResponse> tcs =
        new TaskCompletionSource<ShowContextMenuResponse>();

    WebView.Dispatcher?.BeginInvoke(new Action(() =>
    {
        System.Windows.Controls.ContextMenu popupMenu =
            new System.Windows.Controls.ContextMenu();

        if (!string.IsNullOrEmpty(parameters.LinkText))
        {
            MenuItem buildMenuItem =
                BuildMenuItem("Show the URL link", true,
                              Visibility.Visible,
                              (sender, args) =>
                              {
                                  string linkURL = parameters.LinkUrl;
                                  Console.WriteLine($"linkURL = {linkURL}");
                                  MessageBox.Show(linkURL, "URL");
                                  tcs.TrySetResult(ShowContextMenuResponse.Close());
                              });
            popupMenu.Items.Add(buildMenuItem);
        }

        MenuItem reloadMenuItem =
            BuildMenuItem("Reload", true, Visibility.Visible,
                          (sender, args) =>
                          {
                              Console.WriteLine("Reload current web page");
                              browser.Navigation.Reload();
                              tcs.TrySetResult(ShowContextMenuResponse.Close());
                          });
        popupMenu.Items.Add(reloadMenuItem);

        popupMenu.Closed += (sender, args) =>
        {
            tcs.TrySetResult(ShowContextMenuResponse.Close());
        };

        popupMenu.IsOpen = true;
    }));

    return tcs.Task;
}
Private Function ShowContextMenu(parameters As ShowContextMenuParameters) _
    As Task(Of ShowContextMenuResponse)
    Dim tcs As New TaskCompletionSource(Of ShowContextMenuResponse)()
    WebView.Dispatcher?.BeginInvoke(New Action(Sub()
        Dim popupMenu As New ContextMenu()

        If Not String.IsNullOrEmpty(parameters.LinkText) Then
            Dim linkMenuItem As MenuItem =
                    BuildMenuItem("Show the URL link", True,
                                  Visibility.Visible,
                                  Sub(sender, args)
                                      Dim linkUrl As String = parameters.LinkUrl
                                      Debug.WriteLine( $"linkURL = {linkUrl}")
                                      MessageBox.Show(linkUrl,"URL")
                                      tcs.TrySetResult(ShowContextMenuResponse.Close())
                                  End Sub)
            popupMenu.Items.Add(linkMenuItem)
        End If

        Dim reloadMenuItem As MenuItem =
                BuildMenuItem("Reload", True, Visibility.Visible,
                              Sub(sender, args)
                                  Debug.WriteLine("Reload current web page")
                                  browser.Navigation.Reload()
                                  tcs.TrySetResult(ShowContextMenuResponse.Close())
                              End Sub)
        popupMenu.Items.Add(reloadMenuItem)
        AddHandler popupMenu.Closed, Sub(sender, args)
            tcs.TrySetResult(ShowContextMenuResponse.Close())
        End Sub
        popupMenu.IsOpen = True
    End Sub))
    Return tcs.Task
End Function

完整示例可在我们的存储库中找到: C#, VB.NET

Avalonia UI

browser.ShowContextMenuHandler =
    new AsyncHandler<ShowContextMenuParameters,
        ShowContextMenuResponse>(ShowContextMenu);
private Task<ShowContextMenuResponse> ShowContextMenu(
    ShowContextMenuParameters parameters)
{
    TaskCompletionSource<ShowContextMenuResponse> tcs =
        new TaskCompletionSource<ShowContextMenuResponse>();

    Dispatcher.UIThread.InvokeAsync(() =>
    {
        Avalonia.Controls.ContextMenu? cm = new();
        cm.Placement = PlacementMode.Pointer;
        Point point = new Point(parameters.Location.X, parameters.Location.Y);
        cm.PlacementRect = new Rect(point, new Size(1, 1));

        if (!string.IsNullOrEmpty(parameters.LinkText))
        {
            MenuItem buildMenuItem =
                BuildMenuItem("Show the URL link", true, true,
                              async (sender, args) =>
                              {
                                  string linkURL = parameters.LinkUrl;
                                  Console.WriteLine($"linkURL = {linkURL}");
                                  var box =
                                      MessageBoxManager
                                         .GetMessageBoxStandard("URL", linkURL);
                                  var result = await box.ShowAsync();
                                  tcs.TrySetResult(ShowContextMenuResponse.Close());
                              });
            cm.Items.Add(buildMenuItem);
        }

        MenuItem reloadMenuItem =
            BuildMenuItem("Reload", true, true,
                          (sender, args) =>
                          {
                              Console.WriteLine("Reload current web page");
                              browser.Navigation.Reload();
                              tcs.TrySetResult(ShowContextMenuResponse.Close());
                          });
        cm.Items.Add(reloadMenuItem);

        cm.Closed += (s, a) => tcs.TrySetResult(ShowContextMenuResponse.Close());
        cm.Open(BrowserView);
    });

    return tcs.Task;
}

我们的存储库中提供了完整的实例: C#

禁用上下文菜单

要完全抑制上下文菜单,应使用以下代码:

browser.ShowContextMenuHandler =
     new Handler<ShowContextMenuParameters, ShowContextMenuResponse>(p =>
    {
        return ShowContextMenuResponse.Close();
    });
browser.ShowContextMenuHandler = 
    New Handler(Of ShowContextMenuParameters, ShowContextMenuResponse)(Function(p)
        Return ShowContextMenuResponse.Close()
    End Function)
Go Top