How to customize the WebBrowser context menu in C#

It is hard to find on the internet a detailed and complete solution for modifying the contextual menu due to several reasons.

One of these reasons is that many of the implementations found use the System.Windows.Forms.ContextMenu; you can see one of them here:

Component-Based Development with Visual C#

In these kinds of examples the system menu is not invoked from the ShowContextMenu, instead a user customized menu is. This menu does not allow modifying it as we need.

Another reason is due to the programming language. In the MSDN website a C++ implementation of the ShowContextMenu can be found:

WebBrowser Customization (Part 2)

The problem is that when we want to implement it in C# difficulties such as not being able to call system functions, use the same data types, and many others arise.

Maybe the biggest difficulty can be found when trying to marshall the CComVariant class. A huge variety of solutions can be found on the internet, but they usually do not work (at least in the case mentioned above). Here are some examples of them:

VB Variant Equivalent in C#

Object To Variant

What is the equivalent of Variant data type in C#.NET?

Using the int[] type with size 3 or bigger is one of the ways of solving this.

   1:  int[] variantVar = new int[3];

The VARIANT type can be seen in this MSDN webpage:

VARIANT and VARIANTARG

Once we solved this problem, we can use the IOleCommandTarget function Exec:

   1:  [PreserveSig]
   2:  int Exec(
   3:      ref Guid pguidCmdGroup,
   4:      int nCmdID,
   5:      int nCmdExecOpt,
   6:      // we need to have this an array because callers 
   7:      // need to be able to specify NULL or VT_NULL
   8:      [In, MarshalAs(UnmanagedType.LPArray)] int[] pvaIn,
   9:      [Out, MarshalAs(UnmanagedType.LPArray)] int[] pvaOut
  10:      );

When calling Exec for the first time, we get the handle for the language submenu. We obtain it in variantVar variable:

   1:  int[] nullVariantVar = null;
   2:  int[] variantVar = new int[3];
   3:   
   4:  spCT.Exec(
   5:              ref CGID_ShellDocView,
   6:              SHDVID_GETMIMECSETMENU,
   7:              0,
   8:              nullVariantVar,
   9:              variantVar
  10:              );

Now we must parse variantVar in order to get the result (the handle for the language submenu). The first value that we get is a VARTYPE type, which indicates the kind of variable that we will find next. Then there is a reserved spot of three WORD long, followed by the value we are looking for. So the handle for the submenu is on the second place of the array:

   1:  IntPtr handleSubMenu = new IntPtr(variantVar[2]);

We can replace passing the CComVariant argument to the function by creating a new variable shown in the code below and then call again Exec:

   1:  variantVarIn[0] = VT_INT_PTR;
   2:  // Remember that variantVarIn[1] is reserved
   3:  variantVarIn[2] = handleMenu.ToInt32();
   4:   
   5:  variantVarOut[0] = VT_I4;
   6:  // Remember that variantVarOut[1] is reserved
   7:  variantVarOut[2] = dwID;
   8:   
   9:  // Insert Shortcut Menu Extensions from registry.
  10:  spCT.Exec(
  11:              ref CGID_ShellDocView,
  12:              SHDVID_ADDMENUEXTENSIONS,
  13:              0,
  14:              variantVarIn,
  15:              variantVarOut
  16:              );

We obtain the complete context menu as a result of the instructions shown above. This menu can be modified as much as we desire. Using this, you can add or remove menu items and also their functionality. For example you can call methods implemented in your project from the desired menu item.

Now you can build a customized browser using C# !

Custom Outlook Development

We have a team of experts developing plug-ins for Outlook. We can go beyond Outlook API and develop modifications to those functions that lacks of some features that your product may need. Our team leaders are experts running projects and our customers can feel confident that their product will be released in time. Our sales team can be contacted any time in our office in California  (310) 237-6506.
For more information visit Outlook plugin development

  • Kevin

    It took me some time to find a solution to modifying the context menu in the webbrowser control using C#. It seems you may have what I need, however I have no idea to implement it. What’s the next step? How do I actually do what I need to do? I want to eliminate everything except Copy, Cut and Paste, when interacting text in HTML form elements. Can you help me?

  • Robert

    I have the same issue as Kevin. I have seen several ways of doing this but no one has actually posted complete samples of how to implement this.

  • JP

    Yes an actual demonstation of chopping up the webbrowser context menu would be greatly appreciated.

  • http://pctvsoftwarestore.com PCTV Software

    Very useful post, exactly the information I was looking for. The screen shots will make this a step-by-step process.

  • http://www.oma.com.tw/ 熱水器

    I understand the 2concern,I am very y sad to hear that you got your Supra fixed. I remember reading about some of your doubts3x !.

  • http://www.twitter.com/VinitaCorvera Vinita Corvera

    Detailed article can i have your permision to translate into German for our sites viewers? Thanks

  • http://www.twitter.com/MarcellaLasker Marcella Lasker

    Great post can i translate into Spanish for our sites visitors? Thanks

  • Pablo Yabo

    You can translate if you refer the original article with a link, and the text of the link should be the title of the article.

  • http://wowlevelguide.piczo.com/?cr=3 Tiana Reul

    its excellent as your other articles : D, appreciate it for posting .

  • Ampelio Attanasi

    Don’t get me wrong… but given the title “How to customize the WebBrowser context menu in C#” this article actually explains nothing :-

    • http://blog.databigbang.com/ Sebastian Wain

      Can you elaborate?

      • Ampelio Attanasi

        You may have noticed that other three comments say the same (JP, Robert, Kevin). Here it is not said how you can integrate in a WebBrowser a custom menu entry using C#.
        There are some links, pieces of code about variant but no hints on how to write the body of the ShowContextMenu() function in C# so to add a custom menu.

        Lat’s say I want to add an entry to the WebBrowser menu, how should I change the function?

        public int ShowContextMenu(int dwID, tagPOINT pt, object pcmdtReserved, object pdispReserved)
        { // this will just show the usual menu SFalse == 0x00000001
        return SFalse;
        }

        • http://blog.databigbang.com/ Sebastian Wain

          The article was written in 2008, in the context of Internet Explorer 6 and Internet Explorer 7 related technologies. We can take a look at our source code repository for some code snippet but we don’t have a whole public working example.

          If I remember well, in 2008 this information was enough to solve the problem.

          • Ampelio Attanasi

            Hi Sebastian,

            the technology behind the WebBrowser Activex control has not changed at all – it’s already difficult to make the WebBrowserSite thing work (the interface for the OLE interaction are protected) but once done that *nobody* gives a C# implementation for the contextual menu modification (maybe because MSDN only show -badly- how to do that in C++?)
            Don’t worry, I’ll try to solve it somehow by myself – thank you for your time.
            Bye!