How to add new items to the native Context Menu on a CefSharp control in WinForms

Although we have already written about how to prevent the context menu from appearing in your CefSharp control, because usually you can create better a custom context menu with JavaScript, you may want to still use the default context menu of the CefSharp control:

CefSharp context menu

As you can see the default options aren't really helpful, therefore you need to know how to customize it and add new options.

1. Create a custom Menu Handler

The first you need to do is to create a new class on your project namely MyCustomMenuHandler (you can change the name if you want).This class needs to use the namespace of your application and extend the IContextMenuHandler, therefore you should obviously import the CefSharp, System and System.Windows.Forms namespace into your class and will look as follows:

using System;
using CefSharp;
using System.Windows.Forms;

public class MyCustomMenuHandler : IContextMenuHandler
{
    public void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model)
    {
        
    }

    public bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags)
    {
        return false;
    }

    public void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame)
    {

    }

    public bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback)
    {
        return false;
    }
}

This is just an example and for the moment, the class doesn't do anything, however you should start with this in your custom handler to understand how to add or remove items.

2. Modify the custom handler

To add a new item, use the AddItem method of the IMenuModel argument in the onBeforeContextMenu function. This method expects as first argument an unique integer (providen by you) from 26500 to 28500 that will be used as ID to trigger some action on the onContextMenuCommand. You should therefore start with a new item with the ID 28501 in order to avoid overlapping the Chromium and CEF ID ranges. You can see the full Enum file of the Menu commands of CefSharp here. As second argument you need to provide a string that will be used as the label for the new item on the context menu list.

According to the given ID for the element, you can check which element on the list was clicked on the OnContextMenu command by using a simple if statement and doing something according to it. The following example shows how to add 3 items to the current context menu (to remove any previous element use the model.Clear method), respectively they will show and close the dev tools and the last will display an alert message:

using System;
using CefSharp;
using System.Windows.Forms;

public class MyCustomMenuHandler : IContextMenuHandler
{
    public void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model)
    {
        // Remove any existent option using the Clear method of the model
        //
        //model.Clear();

        Console.WriteLine("Context menu opened !");

        // You can add a separator in case that there are more items on the list
        if (model.Count > 0)
        {
            model.AddSeparator();
        }


        // Add a new item to the list using the AddItem method of the model
        model.AddItem((CefMenuCommand)26501, "Show DevTools");
        model.AddItem((CefMenuCommand)26502, "Close DevTools");

        // Add a separator
        model.AddSeparator();

        // Add another example item
        model.AddItem((CefMenuCommand)26503, "Display alert message");
    }

    public bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags)
    {
        // React to the first ID (show dev tools method)
        if (commandId == (CefMenuCommand)26501)
        {
            browser.GetHost().ShowDevTools();
            return true;
        }

        // React to the second ID (show dev tools method)
        if (commandId == (CefMenuCommand)26502)
        {
            browser.GetHost().CloseDevTools();
            return true;
        }

        // React to the third ID (Display alert message)
        if (commandId == (CefMenuCommand)26503)
        {
            MessageBox.Show("An example alert message ?");
            return true;
        }

        // Any new item should be handled through a new if statement


        // Return false should ignore the selected option of the user !
        return false;
    }

    public void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame)
    {

    }

    public bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback)
    {
        return false;
    }
}

3. Set your custom Menu Handler as default on the browser

Once the class has been modified and is available in your project, then you only need to set the value of the MenuHandler property of your ChromiumWebBrowser as a new instance of your custom menu handler. This can be achieved during the creation of the browser in your current code, for example:

CefSettings settings = new CefSettings();
// Some settings if you have, here
// Initialize cef with the provided settings
Cef.Initialize(settings);

// Create a browser component
ChromiumWebBrowser chromeBrowser = new ChromiumWebBrowser("www.somewebsite or file.com");
// Register your Custom Menu Handler as default
chromeBrowser.MenuHandler = new MyCustomMenuHandler();

// ...
// Rest of your code
// ...

Then our context menu will look like:

Multiple context menu

Happy coding !

Become a more social person