Invoke Hidden Commands in Your Web Browser

Introduction

Generally, when hosting the WebBrowser Control in an MFC application, we call ExecWB method of m_pBrowserApp (IWebBrowser2 interface) to invoke common Web browser commands (zoom the browser, select all text in the browser, and so forth.).

We also invoke queryInterface to get an IDispatch pointer for the IOleCommandTarget interface and call its Exec method to invoke the "Find in This Page" dialog or "View Source" command. But, some dialogs we CAN'T invoke still exist; for example, the "Add To Favorite" dialog and the "Import/Export Wizard" dialog.

We can invoke the "AddFavorite" command and "ImportExportFavorites" command through IShellUIHelper interface, but the former command results in a modeless "Add To Favorite" dialog independent from the application mainframe, while the latter command results in a quit simple consequence.

This article will introduce an innovative but simple way to invoke the MODAL "Add To Favorite" dialog and MODAL "Import/Export Wizard" dialog in your own Web browser.

Background

The idea comes from the IDocHostUIHandler::ShowContextMenu demo of "WebBrowser Customization" in the MSDN. The IDocHostUIHandler::ShowContextMenu demo presents us the way to manually build IE's context menu from correlative resource file "SHDOCLC.DLL" and remove "View Source" from it. The key point of the code is that, after popping up the context menu, it calls a SendMessage() API to send the MenuItem ID returned by TrackPopupMenu() to the "Internet Explorer_Server" window through WM_COMMAND message. So, if we get the MenuItem ID of the "Add To Favorite" command or the "Import/Export Wizard" command, we probably can solve the problems stated above.

......
// Show shortcut menu
int iSelection = ::TrackPopupMenu(hMenu,
                                  TPM_LEFTALIGN | TPM_RIGHTBUTTON |
                                  TPM_RETURNCMD,
                                  ppt->x,
                                  ppt->y,
                                  0,
                                  hwnd,
                                  (RECT*)NULL);
// Send selected shortcut menu item command to shell
LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
......

Using the Code

Some command mesages are handled by the "Internet Explorer_Server" window while some others are handled by its parent "Shell DocObject View" window. Therefore, the fisrt thing is get the Window Handle of the two windows from your CHtmlView. To simple the resolution, I borrow the cute class CFindWnd below from Paul DiLascia.

//===================================================
// MSDN Magazine -- August 2003
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual Studio .NET on Windows XP. Tab size=3.
//
// ---
// This class encapsulates the process of finding a window with a
// given class name as a descendant of a given window. To use it,
// instantiate like so:
//
//        CFindWnd fw(hwndParent,classname);
//
// fw.m_hWnd will be the HWND of the desired window, if found.
//
class CFindWnd {
private:
   //=================
   // This private function is used with EnumChildWindows to find
   // the child with a given class name. Returns FALSE if found
   // (to stop enumerating).
   //
   static BOOL CALLBACK FindChildClassHwnd(HWND hwndParent,
                                           LPARAM lParam) {
      CFindWnd *pfw = (CFindWnd*)lParam;
      HWND hwnd = FindWindowEx(hwndParent, NULL, pfw->m_classname,
                               NULL);
      if (hwnd) {
         pfw->m_hWnd = hwnd;       // found: save it
         return FALSE;             // stop enumerating
      }
      EnumChildWindows(hwndParent, FindChildClassHwnd,
                       lParam);    // recurse
      return TRUE;                 // keep looking
   }

public:
   LPCSTR m_classname;             // class name to look for
   HWND m_hWnd;                    // HWND if found

   // ctor does the work--just instantiate and go
   CFindWnd(HWND hwndParent, LPCSTR classname)
      : m_hWnd(NULL), m_classname(classname)
   {
      FindChildClassHwnd(hwndParent, (LPARAM)this);
   }
};

void CDemoView::InvokeShellDocObjCommand(int nID)
{
   CFindWnd FindIEWnd( m_wndBrowser.m_hWnd, "Shell DocObject View");
   ::SendMessage( FindIEWnd.m_hWnd, WM_COMMAND,
                  MAKEWPARAM(LOWORD(nID), 0x0), 0 );
}

void CDemoView::InvokeIEServerCommand(int nID)
{
   CFindWnd FindIEWnd( m_wndBrowser.m_hWnd,
                       "Internet Explorer_Server");
   ::SendMessage( FindIEWnd.m_hWnd, WM_COMMAND,
                  MAKEWPARAM(LOWORD(nID), 0x0), 0 );
}

Command IDs handled by the "Internet Explorer_Server" window:

#define ID_IE_CONTEXTMENU_ADDFAV        2261
#define ID_IE_CONTEXTMENU_VIEWSOURCE    2139
#define ID_IE_CONTEXTMENU_REFRESH       6042

Command IDs handled by the "Shell DocObject View" window:

#define ID_IE_FILE_SAVEAS               258
#define ID_IE_FILE_PAGESETUP            259
#define ID_IE_FILE_PRINT                260
#define ID_IE_FILE_NEWWINDOW            275
#define ID_IE_FILE_PRINTPREVIEW         277
#define ID_IE_FILE_NEWMAIL              279
#define ID_IE_FILE_SENDDESKTOPSHORTCUT  284
#define ID_IE_HELP_ABOUTIE              336
#define ID_IE_HELP_HELPINDEX            337
#define ID_IE_HELP_WEBTUTORIAL          338
#define ID_IE_HELP_FREESTUFF            341
#define ID_IE_HELP_PRODUCTUPDATE        342
#define ID_IE_HELP_FAQ                  343
#define ID_IE_HELP_ONLINESUPPORT        344
#define ID_IE_HELP_FEEDBACK             345
#define ID_IE_HELP_BESTPAGE             346
#define ID_IE_HELP_SEARCHWEB            347
#define ID_IE_HELP_MSHOME               348
#define ID_IE_HELP_VISITINTERNET        349
#define ID_IE_HELP_STARTPAGE            350
#define ID_IE_FILE_IMPORTEXPORT         374
#define ID_IE_FILE_ADDTRUST             376
#define ID_IE_FILE_ADDLOCAL             377
#define ID_IE_FILE_NEWPUBLISHINFO       387
#define ID_IE_FILE_NEWCORRESPONDENT     390
#define ID_IE_FILE_NEWCALL              395
#define ID_IE_HELP_NETSCAPEUSER         351
#define ID_IE_HELP_ENHANCEDSECURITY     375

The following code demonstrate how to invoke the MODAL "Add To Favorite" dialog.

void CDemoView::OnFavAddtofav()
{
   InvokeIEServerCommand(ID_IE_CONTEXTMENU_ADDFAV);
}

About the Command IDs

As I stated above, the IDocHostUIHandler::ShowContextMenu demo of "WebBrowser Customization" in the MSDN shows a way to manually build IE's context menu from correlative resource file "SHDOCLC.DLL". So, open the file "SHDOCLC.DLL" by using some resource explorer software such as "eXeScope", we can find all the Command IDs (also menu item IDs) used by the WebBrowser Control under menu resources, and all of them are the same in IE 4.x/5.x/6.x according to my tesing.



Downloads

Comments

  • Nice one

    Posted by kirants on 09/15/2004 11:37am

    Well written

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

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • CentreCorp is a fully integrated and diversified property management and real estate service company, specializing in the "shopping center" segment, and is one of the premier retail service providers in North America. Company executives travel a great deal, carrying a number of traveling laptops with critical current business data, and no easy way to back up to the network outside the office. Read this case study to learn how CentreCorp implemented a suite of business continuity services that included …

Most Popular Programming Stories

More for Developers

RSS Feeds