Menu de contexto

Este artigo descreve como trabalhar com o menu de contexto.

Por padrão, o menu de contexto é suprimido para a instância IBrowser. Se uma instância do IBrowserView for inicializada a partir da instância do IBrowser que não tem um tratamento personalizado do menu de contexto, é registrado o tratamento predefinido do menu de contexto. Os itens mostrados no menu de contexto predefinido dependem do item da página Web que foi clicado com o botão direito do mouse, no entanto, na maioria dos casos, contém os seguintes itens: “Voltar”, “Avançar”, “Recarregar”, “Imprimir” e “Ver fonte da página”.

A implementação predefinida do menu de contexto não pode ser modificada. Se você precisar adicionar ou remover alguns itens, você deve criar e registrar a sua própria implementação do manipulador do menu de contexto.

Para criar um menu de contexto personalizado, o manipulador IBrowser.ShowContextMenuHandler deve ser utilizado.

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("Recarregar a página Web atual");
                                  browser.Navigation.Reload();
                                  tcs.TrySetResult(ShowContextMenuResponse.Close());
                              });
            popupMenu.Items.Add(reloadMenuItem);

            // Fecha o menu de contexto quando o navegador pede o foco de volta.
            EventHandler<FocusRequestedEventArgs> onFocusRequested = null;
            onFocusRequested = (sender, args) =>
            {
                BeginInvoke((Action) (() => popupMenu.Close()));
                parameters.Browser.FocusRequested -= onFocusRequested;
            };
            parameters.Browser.FocusRequested += onFocusRequested;

            // Trata o evento para fechar o menu.
            ToolStripDropDownClosedEventHandler menuOnClosed = null;
            menuOnClosed = (sender, args) =>
            {
                bool itemNotClicked =
                    args.CloseReason != ToolStripDropDownCloseReason.ItemClicked;
                if (itemNotClicked)
                {
                    tcs.TrySetResult(ShowContextMenuResponse.Close());
                }

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

            // Mostrar o menu de contexto.
            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("Recarregar a página Web atual")
                    browser.Navigation.Reload()
                    tcs.TrySetResult(ShowContextMenuResponse.Close())
                End Sub)
            popupMenu.Items.Add(reloadMenuItem)

            ' Fechar o menu de contexto quando o browser voltar a pedir o foco.
            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

            ' Trata o evento de fechar o menu.
            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

            ' Mostrar o menu de contexto.
            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

O exemplo completo está disponível no nosso repositório: 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("Mostrar link URL", 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("Recarrega página atual")
                                  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

O exemplo completo está disponível no nosso repositório: 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;
}

O exemplo completo está disponível no nosso repositório: C#

Desativar o menu de contexto

Para suprimir completamente o menu de contexto, o seguinte código deve ser utilizado:

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