Creating Add-ons for Internet Explorer: Toolbar Buttons

As of December 2011, this topic has been archived. As a result, it is no longer actively maintained. For more information, see Archived Content. For information, recommendations, and guidance regarding the current version of Internet Explorer, see IE Developer Center.

Kent Sharkey
July 2007


Creating Toolbar Buttons
Working with the Browser

Summary: Toolbars provide a common means of making application functionality available to users. They may provide access to functionality available elsewhere, or they may group together functionality for accessing a Web site or application. Toolbars in Internet Explorer provide the means for a developer to enhance the application or customize it for clients.

Every Windows user is familiar with toolbars: they are one of the most common means of accessing the functionality of an application.

In Internet Explorer, you can provide additional toolbar buttons for the standard toolbars, or your application can create its own toolbar. The former is useful when you only need to create a few additional buttons. Creating your own toolbar provides you with a location to group a common set of tools together. Because creating new toolbars requires an entirely different mechanism, it will not be covered in this article. This article looks at the registry keys used when creating individual buttons. In addition, it shows an example of creating a DLL that provides the functionality for a new button.

Creating Toolbar Buttons

Creating toolbar buttons for Internet Explorer is very similar to Customizing Menus. You create the functionality for the button in either a COM DLL, script or executable form, then add registry entries to enable Internet Explorer to find and load the button. You can have an item appear as both a menu item and a toolbar item by including the registry settings for both types.

Using an Executable

The simplest item you can add to the standard toolbar is an executable. This provides the user with an easy method of starting your application. Adding this button requires no changes to your application and only a few registry settings.

Why would you want to add a link to an executable to Internet Explorer? The button provides the user with a handy method of starting the application. This could provide a means of starting a network debugging tool or browser accessory application (such as Windows Live Messenger).

To create a button pointing to an executable, add a new key under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Extensions (or the same location under HKEY_CURRENT_USER if you only want the button to be available to the current user). This new key should have a GUID for the name. The new key should have values set to customize the behavior of the button. See the following table for these values. Failing to set all of the required values means that the button will not appear.

ButtonTextThe label for your new button. This will be used to identify the button in the customization dialogs as well as on the toolbar itself if text is displayed.
Default VisibleSet to 'yes' to make the button available by default (however, see the note below). The default is for the button to not be visible by default but to be available in the toolbar customization dialog.
IconThe full path to the file to use as the icon for the button. This may be the path to an icon file or to the ID of the resource within a DLL or EXE.
HotIconThe full path to the file to use as the icon when the icon should be active (i.e., when the mouse is over it) or disabled. This may be the path to an icon file or to the ID of the resource within a DLL or EXE.

GUID identifying the class that will be executed when the button is clicked. Use the value {1FBA04EE-3024-11D2-8F1F-0000F87ABD16} to identify this toolbar button as pointing to an executable. In this case, you must also include the Exec value to identify the executable.

Use the CLSID for the DLL or the value {1FBA04EE-3024-11d2-8F1F-0000F87ABD16} to identify this toolbar button as pointing to a COM DLL. The class should implement the IOleCommandTarget interface. Internet Explorer will call the Exec method on that interface when the button is clicked. If you use the special value above as the CLSID value, you must also include the ClsidExtension value to identify the COM DLL providing the add-on.

ExecThe full path to the file that will be executed when the button is clicked.
ClsidExtensionThe GUID identifying the class implementing IOleCommandTarget for the add-on.
Tooltip(Optional) The text to display when the user hovers the mouse pointer over the toolbar button.

Note: Exec and ClsidExtension are mutually exclusive. Choose only one of these options.

Note: If the user has customized the standard toolbar, a new toolbar button may not initially appear, even if Default Visible is set to yes. It will appear in the Customize Toolbar dialog (Figure 1), and will appear on the toolbar if you select Reset on the dialog.

Figure 1: Customize Toolbar dialog

For example, you can add Notepad to your command bar by creating a new key under the Extensions key in the registry. You can use the GuidGen tool to create a new GUID for this key. Add the following entries to the new key:

CLSID{1FBA04EE-3024-11D2-8F1F-0000F87ABD16} (Identifies this as an executable)
Default VisibleYes
Execc:\windows\notepad.exe (or the path to a particular TXT file)
HotIconC:\Program Files\Microsoft Visual Studio 8\Common7\VS2005ImageLibrary\VS2005ImageLibrary\icons\WinXP\textdoc.ico (Requires that you have expanded the VS2005 image library ZIP file.)
IconC:\Program Files\Microsoft Visual Studio 8\Common7\VS2005ImageLibrary\VS2005ImageLibrary\icons\WinXP\textdoc.ico

Rather than use an icon file to provide the icon, you can also use an embedded resource to provide the icon. In this case, the syntax for the registry entry is to use the following:

Path to file, Resource ID

For example, you might change the HotIcon of the Notepad button to c:\windows\notepad.exe, 203 to display the standard icon when the mouse is over the button.

If you want your toolbar button to support multiple user languages, you must include one or more additional keys under your main extension key. The name of this key should be of the form LCID#### where #### is the locale ID (LCID) you want to support. For example, you would use LCID040C to support French, or LCID0411 for Japanese. Check the List of Locale ID (LCID) Values as Assigned by Microsoft for a full list of LCID values. Once this key is added, it should then have the same set of values shown above.

Using a COM DLL or Script

While starting an executable from a toolbar button provides an easy way of starting that application, it really doesn't do much. There is no way to pass parameters to the new application or get it to perform any action. You can move past these limitations by creating your add-on as script or with a COM DLL. The included sample provides a simple DLL that uses the IWebBrowser2 and IHTMLDocument2 interfaces to analyze the current page and navigate to a Web page of information about the HTML in the document.

As when creating menu items, you should create your add-on as an object that implements IObjectWithSite (Figure 2). This provides the SetSite method, which you can use to store the pointers to the browser.

Figure 2: Adding IObjectWithSite support

Once you have created your new class, there are a few additional steps that will make working with your add-on easier. First, you should add the headers that define the IWebBrowser2 and IHTMLDocument2 interfaces.

#include <shlguid.h>
#include <mshtml.h>

In addition to adding those two header files, you should also add support for the IOleCommandTarget interface. This provides the Exec method that Internet Explorer calls when your add-on is run. Add this interface to the list of base classes for your new class, as well as to the COM map.

class ATL_NO_VTABLE CPageInspector :
  public CComObjectRootEx<ccomsinglethreadmodel>,
  public CComCoClass<cpageinspector, &clsid_pageinspector>,
  public IObjectWithSiteImpl<cpageinspector>,
  public IDispatchImpl<ipageinspector, &iid_ipageinspector, 
    &libid_pagecoplib, /*wmajor =*/ 1, /*wminor =*/ 0>,
  public IOleCommandTarget


Add the declarations for the methods of the IObjectWithSite and IOleCommandTarget interfaces, as well as any additional methods required.

// IObjectWithSite
    STDMETHOD(SetSite)(IUnknown *pUnkSite);
// IOleCommandTarget
    STDMETHOD(Exec)(const GUID *pguidCmdGroup, DWORD nCmdID, 
        DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut);
    STDMETHOD(QueryStatus)(const GUID *pguidCmdGroup, ULONG cCmds, 
        OLECMD *prgCmds, OLECMDTEXT *pCmdText);
    void GenerateReport(BSTR filename);
    BSTR GenerateReportStylesheet();
    BSTR DoImageReport(IHTMLDocument2* pDocument);
    CComPtr<IWebBrowser2> m_spWebBrowser;
        &IID_IOleCommandTarget> m_spTarget;

The SetSite method provides the developer with a means of storing the pointer to the browser.

STDMETHODIMP CPageInspector::SetSite(IUnknown *pUnkSite)
    if (pUnkSite != NULL)
        // Cache the pointer to IWebBrowser2
        CComQIPtr<IServiceProvider> sp = pUnkSite;
        HRESULT hr = sp->QueryService(IID_IWebBrowserApp, 
            IID_IWebBrowser2, (void**)&m_spWebBrowser);
        hr = sp->QueryInterface(IID_IOleCommandTarget,
        // Release pointer

    // Return base implementation
    return IObjectWithSiteImpl<CPageInspector>::SetSite(pUnkSite);

When the button is clicked, it will execute the Exec method of the IOleCommandTarget interface.

STDMETHODIMP CPageInspector::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, 
    DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
    if (m_spWebBrowser != NULL)
        CComBSTR oURL( "c:\\temp\\blah.htm" );

        // Navigate to the report
        VARIANT noArg;
        noArg.vt = VT_EMPTY;
        VARIANT flags;
        flags.vt = VT_I4;
        flags.lVal = navOpenInNewTab;

        m_spWebBrowser->Navigate(oURL, &flags, &noArg, &noArg, &noArg);
        MessageBox(NULL, _T("No Web browser pointer"), _T("Oops"), 0);
    return S_OK;

In addition to the above, you must also ensure your add-on is registered correctly to enable Internet Explorer to load and run it. Open the RGS file for your class and add the following.

    NoRemove Microsoft
      NoRemove 'Internet Explorer'
        NoRemove Extensions
          ForceRemove '{5D578929-E74E-46A2-A810-4F33D011DC51}' 
            = s 'PageCop' {
            val 'Default Visible' = s 'yes'
            val 'ButtonText' = s 'Inspect page'
            val 'CLSID' = s '{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}'
            val 'ClsidExtension' = 
                s '{5D578929-E74E-46A2-A810-4F33D011DC51}'
            val 'Icon' = s 'C:\icons\WinXP\search4doc.ico'
            val 'HotIcon' = s 'C:\ icons\WinXP\search4doc.ico'

The NoRemove entries identify the locations in the registry to write the new entries. They will not be removed when your class is unregistered. The ForceRemove entries will be removed. The GUID {5D578929-E74E-46A2-A810-4F33D011DC51} should be replaced with the GUID for your class. This value is also used as the ClsidExtension value. This identifies the class that will be called when the button is clicked. The class should implement IOleCommandTarget to facilitate dispatching commands. The paths to the icon have been shortened and should represent valid paths to an icon file on your computer. As the Default Visible setting is true, the button should appear by default.

Note: If the user has customized the standard toolbar, a new toolbar button may not initially appear, even if Default Visible is set to yes. It will appear in the Customize Toolbar dialog (Figure 1) and will appear on the toolbar if you select Reset in the dialog.

Working with the Browser

Two of the most common uses for new toolbar buttons are to interact with the browser or the current Web page. You may want to send the browser to a new page or process particular tags on the existing page. Internet Explorer makes either of these two tasks easier by providing the IWebBrowser2 and IHTMLDocument2 interfaces.

The IWebBrowser2 Interface

The IWebBrowser2 interface provides the developer access to the functionality of Internet Explorer. This includes the functionality of the application itself, as well as access to the current HTML document loaded by the browser. The IWebBrowser2 interface includes a number of properties for displaying the various components of the Internet Explorer application, such as the status bar, toolbar(s) and menu bar. Keep in mind, however, that users rarely like an add-on to change these settings. Instead, the most commonly used methods of the IWebBrowser2 interface would include:

  • Navigate

    Changes the page displayed in the browser. This can include creating a new tab if the user has that feature enabled.

  • Navigate2

    Changes the page displayed in the browser. This method differs from Navigate in that it supports setting the method used for the request, enabling POST requests.

  • ExecWB

    Executes a command provided by the application. This is most commonly used to print the current Web page.

  • Document

    Provides a handle to the IHTMLDocument2 interface that represents the document object model (DOM) handle to the current page.

The IHTMLDocument2 Interface

The IHTMLDocument2 interface provides access to the current document loaded in the browser. This is the equivalent of the document class provided to script developers, and the use is similar (although using it in C++ is much more verbose than it is in script). The IHTMLDocument2 interface provides a number of methods to retrieve the elements included in the page. Many of these methods return an IHTMLElementCollection. Each of the items in the collection implement a number of interfaces, including IDispatch, IHTMLElement and an interface representing the particular type of element. The following code shows a typical method of iterating through the elements in the document, finding all the image tags and retrieving the alt attribute. If the alt attribute is NULL, it retrieves the src attribute.

CComPtr<IHTMLElementCollection> spImages;
HRESULT hr = pDocument->get_images(&spImages);

if (SUCCEEDED(hr) && (spImages != NULL))
    long cImages = 0;

    if (cImages > 0)
        for (int i=0; i<cImages; i++)
            CComVariant vIndex(i);
            CComVariant noArg;
            CComPtr<IDispatch> spDispImage;
            // Get the item from the collection.
            spImages->item(vIndex, noArg, &spDispImage);
            if (spDispImage)
                // Get it as an IHTMLImgElement.
                CComQIPtr<IHTMLImgElement> spImage = spDispImage;
                if (spImage)
                    CComBSTR altText("");
                    if (altText == "")
                        CComBSTR srcText("");
                        // Do something with src attribute.

The get_images method of the document returns an IHTMLElementCollection of <img> tags in the document. You can retrieve the individual elements as IHTMLElement objects, but it is safer to initially retrieve them as IDispatch objects and cast them to the appropriate types.


Creating toolbar buttons provides your users with an easy way to use your add-on. In addition, it gives them the flexibility to add or remove the button at their choice. Through the IWebBrowser2 and IHTMLDocument2 interfaces, you have the application and loaded document available. Your code can process or extend the content as needed.

If you need to create multiple buttons for your add-on, you can either use this method to create a number of individual buttons or create a complete toolbar for your add-on.