How to Modify/Remove Right-Click Menu in IE WebBrowser Control

Environment: VC6 SP4, NT4 SP5, WIN 2000/98/95

Here is an easy solution for hiding/replacing the right-click menu on a Web browser window. An example would be my situation. I had to implement a news group reader and writer. The news reader/writer used IwebBrowser2 control as the message display/edit window. If you do a right-click on it, there is an option View Source,.. other menu items. If I had an option, I want to act like I implemented everything from scratch, but the right-click menu put a hole in my plan and revealed that I reused the IE control. Besides, anyway, we didn't want our users to mess around with HTML source code, and so forth, or expose some of them to brain damage from seeing real weird stuff while all they asked for was some news group item. The Web browser captures the right-click and shows the default IE right click menu. So how do I remove it?

I trap the PreTranslateMessage function of the application class (CWinApp derived class). In case of a right click, I will see if it is a Web browser control which generated the message, and if so, I display our menu. Here is our example.

BOOL CWebBrowserTestApp::PreTranslateMessage(MSG* pMsg)
{
  // We have a right click
  if (  (WM_RBUTTONDOWN == pMsg->message) ||
    (WM_RBUTTONDBLCLK == pMsg->message))
  {
    // Now verify it is from our Web browser
    CWebBrowserTestDlg* pWBDlg = 
                     (CWebBrowserTestDlg*)AfxGetMainWnd();
    if(pWBDlg->isThisOurBrowser(pMsg->hwnd))
    {
      // If so, show our menu!
      pWBDlg->showOurMenu();
      // mark as handled
      return TRUE;
    }
    
  return CWinApp::PreTranslateMessage(pMsg);
}

Now that I have trapped the right click, I will have to ask the window that owns the Web browser control to see if the window that got the right click is a Web browser window. It is a little twitchy here. I will have to specifically go case by case, meaning I will have to check, if not this Web browser, the other usage instance of webbrowser and other (meaning if a dialog box had three controls which were Web browsers, I might have a CWnd m_WndBrowser1, CWnd m_WndBrowser2, and CWnd m_WndBrowser3). In the attached example, I have a dialog with one webbrowser control in it. I have a member variable for the Web browser window as follows.

CWnd m_WndBrowser

My function will have to do a little bit more than just matching the window handles. Why so? A nested frame inside IE is again an instance of IE. HTMLs having nested frames will return a different window handle for different frames inside the same parent IE window. So what will be my logic?! I will have to traverse via GetParent from a frame to the parent IE window, whose window handle I already know or till I don't have a parent of type IE. How do we know if it's an IE Window? The Window class name will be "Internet Explorer_Server." That's what the next function does, see if our window is an Internet Explorer, if so we know, the outer shell window will be the parent of doc-view which will be the parent of the IE class window.

// This fn checks if this is a IE type window and returns 
// the outer hosting Shell window handle for it, if it is 
// one! else NULL 
HWND CWebBrowserTestDlg::getParentWebBrowserWnd(HWND hMyWnd)
{
  HWND   hRetWBWnd = NULL;

  static TCHAR tszIEClass[] = "Internet Explorer_Server";
  TCHAR   tszClass[sizeof(tszIEClass)+1];

  // Compare if our window is of type IE class
  ::GetClassName( hMyWnd,tszClass,sizeof(tszClass));
  if(0 == _tcscmp(tszClass, tszIEClass))
  {
   // Then get the Shell which hosts the IE doc view window
     hRetWBWnd = ::GetParent(::GetParent(hMyWnd));
  }
  return hRetWBWnd;
}

// Checks if message window is our WebBrowser control
// and if so returns TRUE
BOOL CWebBrowserTestDlg::isThisOurBrowser(HWND hMyWnd)
{
  HWND hWndOurWebBrowser = (HWND)m_WndBrowser.GetSafeHwnd();
  // Get the Parent Web browser window if any
  HWND hParentWBWnd = getParentWebBrowserWnd(hMyWnd);

  // Now, we can have nested frames .. 
  // meaning a frame inside a frame is yet another webbrowser
  // So our m_WndBrowser guy can be way up there .. 
  // so we have to iterate up to him through parent frames
  // till we have a match or no more WB type parent
  while(  (NULL != hParentWBWnd) &&
    (hParentWBWnd != hWndOurWebBrowser))
  {
    // Get the Parent of the Web browser window
    //I have, recursively
    hParentWBWnd = 
           getParentWebBrowserWnd(::GetParent(hParentWBWnd));
  }
  return (NULL != hParentWBWnd);
}

Now the next function is a normal function to show a popup menu from a resource and I am not going to explain it. People who need explanation, please read the help file for TrackPopupMenu.

// This is a trivial fn which gets a submenu from a resource
// and displays it at the current cursor position
void CWebBrowserTestDlg::showOurMenu()
{
  POINT  CurPoint;
  GetCursorPos(&CurPoint);

  CMenu  ReplaceMenu;
  //Make your custom menu here
  ReplaceMenu.LoadMenu(IDR_RIGHTCLICK);
  // Do we have a menu loaded?
  if(::IsMenu(ReplaceMenu.m_hMenu))
  {
    // this is my popup menu
    CMenu* pMyPopup = ReplaceMenu.GetSubMenu(0);
    if(NULL != pMyPopup)
    {
      // Show it
      pMyPopup->TrackPopupMenu (TPM_LEFTALIGN | TPM_RIGHTBUTTON,
                                CurPoint.x, 
                                CurPoint.y, this );
      // deleting me and my parent when I am done
      pMyPopup->DestroyMenu();
      ReplaceMenu.DestroyMenu();
    }
  }
}

Downloads

Download demo project - 16.6 Kb



Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: May 11, 2015 @ 1:00 p.m. ET / 10:00 a.m. PT One of the languages that have always been supported with the Intel® RealSense™ SDK (Software Developer Kit) is JavaScript, specifically so that web-enabled apps could be created. Come hear from Intel Expert Bob Duffy as he reviews his own little "space shooting" game where the orientation of your face controls the aiming reticle to help teach developers how to write apps and games in JavaScript that can use facial and gesture …

  • There has been growing buzz about DevOps. DevOps is a methodology that unites the often separate functions of software development (Dev) and production and operations (Ops) into a single, integrated, and continuous process. DevOps is about breaking down the barriers between Dev and Ops. It leverages people, processes, and technology to stimulate collaboration and innovation across the entire software development and release process. Dev and Ops should always be part of an integrated process, but that's not …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date