Disabling TCppWebBrowser's context menu or "right-click" menu.

By: Vincent Drake

Abstract: Implementing IDocHostUIHandler in a simple COM object quickly solves this problem at the source.

Were the TCppWebBrowser a simple VCL control, disabling the popup menu might be as simple as assigning NULL to the PopupMenu property. For better or worse, it is not simply a VCL control, but a wrapper around the ActiveX version of Internet Explorer. Much goes on beneath the scenes of the TCppWebBrowser component the VCL is not aware of. Microsoft provides a number of interfaces and APIs for manipulating and fine tuning the web browser components behavior.

The interface concerning us right now is IDocHostUIHandler. In depth description of the interface can be found on the MSDN here: http://msdn.microsoft.com/workshop/browser/hosting/wbcustomization.asp?frame=true. Basically, the application hosting the web browser component will implenent this interface and pass an interface to the web browser component using a call to ICustomDoc::SetUIHandler. The browser will call methods on the interface and behave according to how the host implemented the interface. This is the same concept as callback functions, but uses a complete interface instead of a single function pointer.

In the example that follows, we demonstrate the implementation of IDocHostUIHandler for the purpose of supressing the browser's context menu, or right-click menu as it's more commonly known. This is useful for applications that display HTML documents, but want to hide this fact or do not want the user to have access to the functionality normally exposed by Internet Explorer. The example only scratches the surface of what is possible using IDocHostUIHandler, as it only implements one function. Developers who make heavy use of the web browser component may wish to investigate further the faculties available with the IDocHostUIHandler interface.

Example:

Start with a new application and drop a TCppWebBrowser on the main form. Modify Unit1.h to match the listing below:


// File: Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include 
#include 
#include 
#include 
#include "mshtmhst.h"
#include "SHDocVw_OCX.h"
#include 
//---------------------------------------------------------------------------

// Simple implementation for IDocHostUIHandler and IUnknown interfaces
// Implementation returns E_NOTIMPL for all IDocHostUIHandler methods except
// ShowContextMenu. See comment block preceeding that ShowContxtMenu for 
// further information.
class MyDocHandler :public IDocHostUIHandler
{
  long refcount;
public:

  MyDocHandler() :refcount(1){ }

  virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID classid, void** intf) {
    if (classid == IID_IUnknown)
      *intf = (IUnknown*)this;
    else if (classid == IID_IDocHostUIHandler)
      *intf = (IDocHostUIHandler*)this;
    else
      return E_NOINTERFACE;
    return S_OK;
  }

  virtual ULONG STDMETHODCALLTYPE AddRef() {
    InterlockedIncrement(&refcount);
    return refcount;
  }

  virtual ULONG STDMETHODCALLTYPE Release() {
    InterlockedDecrement(&refcount);
    if (refcount == 0)
      delete this;
    return refcount;
  }

  // Returning S_OK tells the web browser that it need not display its
  // own context menu, presumably because the application hosting it has
  // displayed its own menu to replace it.
  // Since our host does not display any, no context menu is shown.
  virtual HRESULT STDMETHODCALLTYPE ShowContextMenu(
    /* [in] */ DWORD dwID,
    /* [in] */ POINT __RPC_FAR *ppt,
    /* [in] */ IUnknown __RPC_FAR *pcmdtReserved,
    /* [in] */ IDispatch __RPC_FAR *pdispReserved) {


        return S_OK;
    }

  virtual HRESULT STDMETHODCALLTYPE GetHostInfo(
    /* [out][in] */ DOCHOSTUIINFO __RPC_FAR *pInfo) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE ShowUI(
    /* [in] */ DWORD dwID,
    /* [in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
    /* [in] */ IOleCommandTarget __RPC_FAR *pCommandTarget,
    /* [in] */ IOleInPlaceFrame __RPC_FAR *pFrame,
    /* [in] */ IOleInPlaceUIWindow __RPC_FAR *pDoc) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE HideUI( void) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE UpdateUI( void) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE EnableModeless(
    /* [in] */ BOOL fEnable) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate(
    /* [in] */ BOOL fActivate) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(
    /* [in] */ BOOL fActivate) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE ResizeBorder(
    /* [in] */ LPCRECT prcBorder,
    /* [in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
    /* [in] */ BOOL fRameWindow) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(
    /* [in] */ LPMSG lpMsg,
    /* [in] */ const GUID __RPC_FAR *pguidCmdGroup,
    /* [in] */ DWORD nCmdID) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE GetOptionKeyPath(
    /* [out] */ LPOLESTR __RPC_FAR *pchKey,
    /* [in] */ DWORD dw) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE GetDropTarget(
    /* [in] */ IDropTarget __RPC_FAR *pDropTarget,
    /* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE GetExternal(
    /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE TranslateUrl(
    /* [in] */ DWORD dwTranslate,
    /* [in] */ OLECHAR __RPC_FAR *pchURLIn,
    /* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut) {
        return E_NOTIMPL;
    }

  virtual HRESULT STDMETHODCALLTYPE FilterDataObject(
    /* [in] */ IDataObject __RPC_FAR *pDO,
    /* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet) {
        return E_NOTIMPL;
    }
};

//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Modifications to Unit1.cpp are listed below:

//File: Unit1.cpp
//---------------------------------------------------------------------------

#include 
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "SHDocVw_OCX"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

// The constructor for TForm1 navigates the web browser to www.hotmail.com,
// and waits for the page to completely load before passing a pointer to 
// MyDocHandler to the browser via SetUIHandler.

__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner) {
    dochandler = new MyDocHandler;
    CppWebBrowser1->Navigate(WideString(L"www.hotmail.com"));
    while(CppWebBrowser1->Busy)
      Application->ProcessMessages();

    ICustomDoc *custdoc;
    CppWebBrowser1->Document->QueryInterface(&custdoc);
    if (custdoc)
      custdoc->SetUIHandler(dochandler);
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1() {
  dochandler->Release();
}

//---------------------------------------------------------------------------


Server Response from: ETNASC02