This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


Cutting Edge
cutting@microsoft.com       Download the code (13KB)
Dino Esposito

Customizing Microsoft Internet Explorer 5.0
N
owadays, writing a completely custom browser is not a difficult task—provided you can rely on the WebBrowser control that's available starting with Microsoft® Internet Explorer 3.0. The browser helper objects (BHO) introduced with Internet Explorer 4.0 gave you an opportunity to add even complex new functionality to the original browser. A couple of working examples of BHOs can be found in Scott Roberts' article in the May 1998 issue of MIND and in the January/February 1999 issue of MSDN™ News.
      There is just one aspect missing from all these pre-Internet Explorer 5.0 programming goodies: you couldn't associate new functionality with the browser's user interface. You had no way to add new toolbar buttons or to customize any of the menus. Thankfully, this problem has been solved with Internet Explorer 5.0.
      Let's look at the new ways you can interface with the Internet Explorer UI, the points at which you're allowed to intervene, and what you can actually obtain through code. I'll briefly review the highlights of BHOs, focusing on scripting-related aspects of Internet Explorer 5.0 customization and registry changes. Windows Script Host (WSH) will be my development environment of choice here.

Customizable Aspects of Internet Explorer 5.0
      Figure 1 summarizes the aspects of Internet Explorer 5.0 that can be considered customizable. In particular, you can add new toolbar buttons and menu items. For each, you specify the text and icons to add to the particular object, as well as the code that you should run when the user selects the new entry. The browser has a number of context menus that appear when you right-click an image, a document, a table, an ActiveX® control, selected text, and other items. You can add new items to any of the context menus and have full control over the whole process that displays the menu. In other words, you can detect when the context menu is about to be shown and add your changes on the fly.
      Internet Explorer 5.0 comes with a number of related applications that let you work outside the Web, such as email or news readers, HTML editors, and so on. You can modify the list of available applications to fit your needs. The search bar can be enhanced and you can even use your own search panel.
      Technologies like Dynamic HTML (DHTML), behaviors, and XML provide excellent tools for customizing and extending browser features. You can create a browser implementing the IDocHostUIHandler interface, and expose a completely custom object model through that interface's External property (see "Take Total Control of Internet Explorer with Advanced Hosting Interfaces," by Scott Roberts in the October 1998 issue of MIND). You can use behaviors to customize the way a certain HTML tag reacts to user and browser solicitations by extending it with new methods, properties, and events.

Customization Techniques
      Customization of the Internet Explorer 5.0 user interface involves four elements: COM components, HTML, script files, and the registry. By writing a special COM component or script file and entering some keys and values to the registry, you can personalize the Internet Explorer interface. As I mentioned earlier, I won't discuss the COM stuff in depth here, but I will give you an overview of the COM component you can write to interact with Internet Explorer 5.0.
      There are basically four types of Internet Explorer-specific COM objects: BHOs, BHOs with custom commands, command-only objects, and the Explorer deskband.
      A BHO is a simple COM server that is only required to implement the IObjectWithSite interface. You can create a BHO with ATL by choosing the Internet Explorer object template from the ATL objects gallery. BHOs are also supported by Windows Explorer (if you're running shell version 4.71 or greater) and Internet Explorer 4.0. BHOs don't necessarily link with the UI; they are just actions you take when starting the browser. BHOs are passed a pointer to the browser's IUnknown interface.
      You can add new commands to the browser by writing BHOs, or even simpler COM objects, that implement IOleCommandTarget. With this interface, Internet Explorer 5.0 knows how to ask your component to execute a function. Such a component needs to be associated with a menu item or a toolbar button. The difference between a BHO and a COM server implementing IOleCommandTarget is that a BHO can easily access (via the received IUnknown pointer) any object model exposed by the document being viewed.
      An Explorer deskband is a docking window that you can employ as the left pane of your browser. By default, the deskband is a window within Explorer that shows the shell's namespace. Other predefined deskbands allow you to see the Search, History, and Favorites panels. Usually, the available deskbands are listed under the View | Explorer Bar menu both for Windows Explorer and Internet Explorer (see Figure 2).

Figure 2: Available Deskbands
      Figure 2: Available Deskbands

      Writing a custom deskband is neither painfully difficult nor particularly easy. A few examples can be found in the latest Platform SDK.

Adding a New Toolbar Button
      To add a new button to the Internet Explorer 5.0 toolbar, you just write some new entries to the system registry. You define the icons to be used, the text to be shown, and what happens when someone clicks the button. A toolbar button always has a corresponding menu item, which is automatically added at the bottom of the Tools menu. The Windows Scripting Host (WSH) script shown in Figure 3 demonstrates how to create a new button called Run Script. The final effect is shown in Figure 4.

Figure 4: The New Run Script Toolbar Button
      Figure 4: The New Run Script Toolbar Button

      There are two categories of information to be added for a new button: configuration and behavior. Figure 5 shows the entries that describe the button. All the entries mentioned here are strings (type REG_SZ). Notice that if Default Visible is set to No, the button won't appear on the toolbar, although it will still be available through the toolbar's Customize dialog. If the user has already customized the toolbar, the button will not appear on the toolbar automatically no matter the value of Default Visible.
      The Clsid entry can take two possible GUIDs as values:
 {E0DD6CAB-2D10-11D2-8F1A-0000F87ABD16} 
and
 {1FBA04EE-3024-11D2-8F1F-0000F87ABD16}
Use the first GUID if you're attaching a deskband to the button, otherwise use the second one.
      These entries must all be written to the following root key:

 HKEY_LOCAL_MACHINE
   \Software
     \Microsoft
       \Internet Explorer
         \Extensions
 
Under this path, however, you have to create a new key with a unique GUID. You can use GuidGen.exe to generate a new one. Incidentally, this is exactly what I did to come up with the GUID in Figure 3. Notice that as long as you use the HKEY_LOCAL_MACHINE root node, the button will be visible to all users on the specified machine. If you want it to apply only to certain users, enter the registry changes under the HKEY_CURRENT_USER node instead.
      These changes are sufficient to make a new button appear on the Internet Explorer toolbar. The icons must include two formats each: 16X16 (16 colors) and 20X20 (256 colors). You can create these icons with the integrated resource editor of Visual Studio®. To give the button an associated behavior, you have three options: running an executable, running a script or an HTML page, or invoking a command defined in some COM component implementing the IOleCommandTarget interface. Let's take a look at what you have to add to the registry in each case.
      To spawn an external program you need to add a further value, Exec, whose content is the fully qualified name of the executable. My tests indicate that you can't specify a command-line argument. For example,
 notepad.exe 
works fine, while
 notepad.exe file.txt
doesn't, even if you surround the whole thing with quotes.
      If your goal is to run a Web page or a script file, then you have to change the entry. Use Exec for a Visual Basic® Scripting Edition (VBScript) or JScript script, and use Script for an HTML page. There are some subtle differences between these two options. Exec means that the specified file is executed through the program registered to manage that type of file. If you use the Exec entry with an HTML file, you force the default browser (in most cases Internet Explorer 5.0 itself) to navigate to that page. If you use Exec with a .vbs file, you simply end up executing that code—provided that you have WSH properly installed. Running a VBScript or a JScript file as a standalone executable doesn't let you access the current instance of the browser and the object model exposed by the currently viewed document. If you want to use these objects, you must resort to using an HTML file that contains only script code and run it through a Script (not Exec) entry. For example, this code
<SCRIPT LANGUAGE="JavaScript">
     var parentwin = external.menuArguments;
     var doc = parentwin.document;
     var sel = doc.selection;
     var rng = sel.createRange();
     var str = new String(rng.text);
     if(str.length == 0)
         rng.text = "HELLO, MIND!";
     else
         rng.text =  str.toUpperCase();
 </SCRIPT>
adds "HELLO, MIND!" to the current page when you click the button.
      Using the Script entry and a script-only HTML file allows you to use the External object to access the document's object model. If you put any decorative tags in this HTML file, they will be ignored.
      Finally, you can establish a link between an Internet Explorer 5.0 toolbar button and a COM object via the ClsidExtension entry. Its content is the CLSID of the COM object implementing the IOleCommandTarget interface. If you have a deskband, use the BandClsid entry instead of ClsidExtension.

Accessing the Document Object Model
      I mentioned earlier that if you want to access the document object model (DOM), you have to resort to the Script entry and a script-only HTML file. Well, that's not completely true. Or rather, it's true if you want to rely on the standard capabilities of Internet Explorer. However, if you have a brave heart and know how to build a simple Visual Basic-based COM object, you can have both your WSH scripts and a standalone executable that accesses the object model of the document being viewed through Internet Explorer.
      You need two pieces of information: the instance of Internet Explorer that's running your script, and the way to connect to a running instance of Internet Explorer. Every running instance of Internet Explorer has its own window, and every window has its own unique handle (HWND). Internet Explorer 5.0 makes available a COM object that returns the collection of all the running instances of both Explorer and Internet Explorer. Such an object is of type ShDocVw.ShellWindows. It was also available for Internet Explorer 4.0, albeit with a slightly different name. Once you've created an instance of this object, you have a reference to all the running instances of Internet Explorer. You just have to distinguish between Windows Explorer and Internet Explorer and realize which instance of Internet Explorer is actually running your script.
      A user who wants to run a script would click on a toolbar button, which automatically means that the foreground window is Internet Explorer. The handle of the foreground window is returned by the GetForegroundWindow API function. Hence, the algorithm is:

  1. Get the collection of the active instances of Internet Explorer.
  2. Walk the collection.
  3. For each instance of Internet Explorer, compare the handle of the main window with the foreground window.
  4. There's just one possible match. When you've found that, you've found the instance of Internet Explorer that ran your script.
      To execute all of this from within a WSH script, I wrote a very simple Visual Basic-based object whose source code is shown in Figure 6. This object (the progID is IE5Script.Instance) exposes four properties: HWND, Title, IEDocument, and IEObject. HWND returns the handle of the foreground window. Title returns the caption of the foreground window. IEDocument matches the foreground window with the various copies of Internet Explorer and returns the Document object of the right instance. (If you expect to execute this from a script associated with an Internet Explorer toolbar button, you must have at least one copy of Internet Explorer running!) Finally, IEObject returns a reference to the application object of Internet Explorer. Through the value retrieved by this property, you can drive the whole Internet Explorer object model.
      A script that wants to access the DOM can do something like this:
 Set obj = CreateObject("IE5Script.Instance")
 Set myPageObj = obj.IEDocument
From now on, myPageObj can be used to access the various items that form the DHTML object model. For example, you could enumerate all the links in a page:
 Set obj = CreateObject("IE5Script.Instance")
 Set myPageObj = obj.IEDocument

 For Each lnk In myPageObj.links
     txt = txt & lnk.href & vbCrLf
 Next
 MsgBox txt
Figure 7 shows the final result.
Figure 7: Enumerating Links in a Page
      Figure 7: Enumerating Links in a Page

Modifying the Menus
      You can also modify the Internet Explorer 5.0 menu without affecting the toolbar. As mentioned earlier, each toolbar button has a corresponding command in the Tools menu. However, this is only true in the default case. In other words, a new command goes under the Tools menu unless you specify otherwise. Unfortunately, you can't add the menu item wherever you want. You have just two choices: you can add it under the Help menu or the Tools menu. By default, it goes under Tools unless you create another string value called MenuCustomize when you're setting up the registry entries. Set MenuCustomize to "Help" and the menu item will appear under the Help menu. Set it to any other string (say, "File") and the menu item will appear under the Tools menu.
      When you specify the text for the item (its value is MenuText), you can't specify your choice of underlined character to denote a keyboard shortcut. This is done as a precaution so that you don't introduce a conflict.

The Context Menus
      When it comes to customizing the browser, the context menus are frequently one of the aspects you want to control. One of the typical problems you might have is needing to hide the source code of the page from curious users. Until the release of Internet Explorer 5.0, this was possible only by implementing IDocHostUIHandler in your WebBrowser's container. With Internet Explorer 5.0, a slightly enhanced DHTML object model lets you get the same result with script code. The latest Platform SDK contains a made-to-measure example under the path \samples\internet\ie\ie50\OnContextMenu.
      To hide the standard context menu, just use the following piece of script code:

 <body oncontextmenu="return false">
However, if you assign a procedure to the oncontextmenu property, you can decide at runtime whether to display a menu and, if you do, which one should appear. You can also build your own menu on the fly, as demonstrated in the Platform SDK example.
      If you don't mind all the standard context menu items, but simply want new and more specific items, describe them in a registry subtree located under:
 HKEY_CURRENT_USER
   \Software
     \Microsoft
       \Internet Explorer
         \MenuExt
Each subkey of this node will be considered a new item for any context menu. Notice that now you must work under HKEY_CURRENT_USER. For example, you could create a key called "Do Something…" and set its default value to the following HTML page:
 <SCRIPT LANGUAGE="JavaScript">
     var parentwin = external.menuArguments;
     var doc = parentwin.document;
     alert("My parent window is: " + doc.title);
 </SCRIPT>
 
From now on, any context menu of Internet Explorer 5.0 includes a "Do Something…" item, which prompts you with the title of the current page. In Figure 8, you can see how the context menu for both images and selected text show off a brand new item.
Figure 8: A New Context Menu Item
      Figure 8: A New Context Menu Item

      As for toolbar buttons, the HTML code associated with the command will be run in a hidden dialog box that is passed the parent window object through the external.menuArguments property.
      You can also limit the number of context menus where a given command appears. To do so, add another value and name it Contexts. Note that it must be a DWORD value. Assign it any combination of the hex values listed in Figure 9. For example, a value of 0x12 will cause the new item to appear only on the Image and Text context menu, as shown in Figure 8.

Related Applications
      Internet Explorer 5.0 works in conjunction with a number of other applications: HTML editors, mail and news clients, calendars, contact managers, and conferencing. Usually, it detects and lets you choose only a few of the applications you may have on your machine. Once Internet Explorer 5.0 detects such programs, it lists them through the Internet Options dialog box (see Figure 10).

Figure 10: Internet Explorer-related Programs
      Figure 10: Internet Explorer-related Programs

      Let's see how to make other applications available. Five out of six categories can be managed through this registry node:
 HKEY_LOCAL_MACHINE
   \Software
     \Clients
These categories include: Mail, News, Internet Call (conferencing), Calendar, and Contacts. To define a new mail reader (even a dummy entry), create a new node under the Mail key and duplicate the settings you can see for the other entries. Figure 11 shows the result.
Figure 11: Registry Settings for a New Mail Reader
      Figure 11: Registry Settings for a New Mail Reader

      The remaining category of Internet Explorer 5.0 applications is HTML editors. If an HTML editor is made available, it must first be configured elsewhere in the registry. The key to look for is:
 HKEY_CLASSES_ROOT 
   \.htm
     \OpenWithList
Under this node, you can create a new key for any new program that processes HTML file names on the command line. Take note of the OpenWithList key—it's a sneak preview of a shell feature that's scheduled to ship with Windows 2000. If you're already running a prerelease version of Windows 2000, chances are you already noticed that some file types have dropdown menus in their context menus under the Open With item, allowing you to select from multiple programs to open the file type. All the items shown in this list are taken from the OpenWithList registry key.

Deploying the Customization
      So far I've discussed a number of techniques you can employ to make Internet Explorer better suit your needs. As you can see, almost all the changes that are required to customize Internet Explorer end up being registry tweaks that must take place on the local client machine.
      To wrap things up, let me address some strategies you can follow in order to deploy any change in a fairly automatic way.
      You have three options: remote administration of the registry, running WSH scripts locally, or using a self-installing ActiveX module that users download from a fixed URL. In the first case, the system administrator is free to access and manipulate the registry of the connected machines from a remote workstation and can enter any needed change. In the second case, users are required to run a script-based setup procedure locally. From the developer's point of view, these two approaches look much the same.
      The third option is the one I prefer and which I've often employed, although in a slightly different context. When a user wants to update his browser, he just connects to a fixed URL on the intranet. That page contains an ActiveX control, CAB file, or Java-language applet—the choice is yours—which gets downloaded locally and works in the background.

Summary
      I've shown you the major customization features of Internet Explorer 5.0, focusing on the configuration aspects of the browser as opposed to more development-oriented topics such as behaviors and object model extensions. (For more information on behaviors and object model extensions, please see past issues of MIND and MSDN™ News.) For more information about the administrative concepts covered in this column, you can refer to the latest MSDN CDs; look under the Platform SDK area for the Web Services | Workshop node.

From the November 1999 issue of Microsoft Internet Developer.