Disabling the context menu in the .Net CF WebBrowser Control

Standard

image

Although initially impressive, the WebBrowser control in the .NET Compact Framework 2.0 lacks the ability to be customised in a few important areas. An obvious one that people are asking about seems to be the ability to remove the default context menu.

None of the obvious solutions , such as setting the ContextMenu property to null seem to work.

The Problem
The internal PIE control that the WebBrowser control wraps has a COM property to disable it, but this is not exposed.

So how can we set the property?

The .NET CF 2.0 provides the answer. It introduced some new features that allows straight forward interaction with COM objects and controls.

Doing this with the WebBrowser control involves sending a special windows message (DTM_BROWSERDISPATCH) to the windows handle of the control to retrieve a pointer to the IDispatch interface, converted into an object (using the GetObjectForIUnknown call) , which is then cast to a marked up interface with the appropriate identifiers. These are found webvw.h which is part of the Compact Framework SDK.

This technique will only work for Windows Mobile (not Smartphone) based devices. For my own projects I use a compiler directive to screen avoid the COM calls on the Smartphone platform.

The Solution

I have cut down the solution to it’s bare essentials and encapsulated it in the class WebBrowserContactMenu. You should be able to reuse this class, unaltered in your own project.

Warning: Currently this solution WILL ONLY WORK FOR Windows Mobile 2003!   It is supposed to work for WM5 and above also (it all seems correct) but for some reason the SendMessage to DTM_BROWSERDISPATCH is not working at all.   I have researched the problem but as yet cannot find a workaround.  I will update this article if I do.  Any suggestions are welcome.

Imports System.Runtime.InteropServices
Imports System.Runtime.CompilerServices
Public Class WebBrowserContextMenu
Private moWebBrowser As WebBrowser
Public Sub New(ByVal control As WebBrowser)
moWebBrowser = control
End Sub
Const WM_USER As Integer = &H400
Const DTM_BROWSERDISPATCH As Integer = (WM_USER + 124)
Declare Function SendMessageLongRef Lib “Coredll” Alias “SendMessageW” (ByVal HWND As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As Integer) As Integer
Public Property Enabled() As Boolean
Get
Return mGetBrowserInterface.ContextMenuEnabled
End Get
Set(ByVal value As Boolean)
mGetBrowserInterface.ContextMenuEnabled = value
End Set
End Property

Private Function mGetBrowserInterface() As IBrowserBareEssentials

Dim liPtr As Integer = 0
SendMessageLongRef(moWebBrowser.Handle.ToInt32, DTM_BROWSERDISPATCH, 0, liPtr)

Return CType(System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(CType(liPtr, IntPtr)), IBrowserBareEssentials)

End Function

<ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIDispatch), Guid(“698E3FC9-70C3-11D0-81E8-00A0C90AD20A”)> _
Public Interface IBrowserBareEssentials

<DispId(185)> Property ContextMenuEnabled() As Boolean
End Interface
End Class

In the example project, a simple WebBrowser application hosts this class, instantiating it and using radio buttons to toggle the button. Here’s what the form code looks like:

Public Class Form1
Private moContextMenu As WebBrowserContextMenu
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
WebBrowser1.Navigate(New Uri(txtUrl.Text))
moContextMenu = New WebBrowserContextMenu(WebBrowser1)
End Sub
Private Sub cmdGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdGo.Click
WebBrowser1.Navigate(New Uri(txtUrl.Text))
End Sub
Private Sub optEnabled_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles optEnabled.Click
moContextMenu.Enabled = optEnabled.Checked
End Sub
Private Sub optDisabled_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles optDisabled.Click
moContextMenu.Enabled = optEnabled.Checked
End Sub

End Class

Download the sample project. (14K)

Conclusion

The purpose of this article was to provide a direct solution to the context menu problem. I have by no means an exhaustive description of using COM with WebBrowser, but this may help as an introduction. At a future date I will share other uses for this technique.

Share this post :

kick it on DotNetKicks.com

About these ads

9 responses »

  1. I have tried your solution without any changes on my Windows Mobile 5 device, (Compact Framework 2 SP1 installed), but it doesn’t work. When I try to disable the ContextMenu at runtime I always get the an ArgumentNullException for ‘mGetBrowserInterface()’ in Line
    “Return CType(System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(CType(liPtr, IntPtr)), IBrowserBareEssentials)”.

    Seems like the IUnknown-Interface of the Browserobject is not found… ???

  2. The same for me, under windows ce 2003 it works perfect, under windows mobile 5 throws the same exception as sirlizium says. Has anyone solved it?

  3. yeah, i have the same problem, i’m using windows mobile 6 with cf 2.0 and when i try to disable the context menu at runtime i get a lot of errors… Someone can help me?

  4. Pingback: Best way to do this?

  5. Pingback: Mobile Development : Disable WebBrowser's Context-Menu in NETCF applications

  6. I am looking for it…… but till now i am not able to find it, is it possible to show our own menu in the context menu of browser control instead of default? if any one has succeeded in overriding it please comment here

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s