Advanced CHtmlView Hosting
The WebBrowser control (and CHtmlView, as its wrapper) is a great tool. It saves you quite a bit of work to enable web-browsing features inside your applications. But since it’s not written by you, you have a limited amount of control over how it looks and acts. The developers of WebBrowser control and MSHTML have provided use some advanced hosting features, so that once an application implements them, it can customize the behavior of the WebBrowser control in more aspects. These customizations are accomplished by a set of interfaces. The host application has to implement these interfaces, and MSHTML will query its host for these interfaces, and uses them if available. These interfaces are IDocHostUIHandler, IDocHostShowUI, and ICustomDoc, which are introduced with Internet Explorer 4.0 for the first time. Internet Explorer 5.5 introduced another interface, called IDocHostUIHandler2, too. Note that because of a bug in IE 5.5 that is described in the Knowledge Base article ID Q272968, IDocHostUIHandler2 will not work with IE 5.5, but it works well with IE 6.
One of the less known interfaces which can be used to achieve cool features of the Web Browser control is the IDocHostUIHandler interface. This interface allows the programmer to customize the behavior of the Web Browser control easily. The MSHTML code will call this interface’s methods to query options you would like to use, and the interface implementation inside your own code will pass the desired parameters back to MSHTML, and MSHTML will handle the details for you. So, using IDocHostUIHandler is as easy as implementing that interface!
Well, I admit that I lied on the above line. It is a bit tricky to implement IDocHostUIHandler, and get it to work, especially when you want to incorporate this into an MFC application which is using CHtmlView. The Microsoft Knowledge Base article ID Q236312 describes how this should be done, but I think that it’s not exactly the best way to do it. Using that method requires manual changes to the application class InitInstance( ) functions, including header files here and there, and all this is not good in my opinion. I wrote some classes which do a better encapsulation, in a way that the only change you need to make to an existing application to add support for the IDocHostUIHandler interface (as well as IDocHostShowUI and IDocHostUIHandler2 interfaces) is deriving your HTML view class from my class instead of CHtmlView. I have gathered all the necessary code inside the sample application downloadable at the bottom of the article, and I will let you know how to use the classes. The good news is that MFC 7 (which comes with Visual Studio .NET) has native support for IDocHostUIHandler inside its CHtmlView implementation, and they are as easy as a piece of cake to use. Because of this, I tried to provide a similar interface to MFC 7 version of CHtmlView, which allows an MFC 6 application using my custom class to be ported to MFC 7 in less than one minute (yes, I’m not joking!).
The other advanced hosting interface is IDocHostShowUI. This interface allows the application provide its own custom message boxes and help files, and the WebBrowser control will use them, instead of its default message boxes and help files. This interface is not supported in MFC 7, but my classes provide support for this as well. This interface has only two methods, ShowHelp( ) and ShowMessage( ). To use these functions, all the thing you need to do is to derive your HTML view class from my class, and override the OnShowHelp( ) and OnShowMessage( ) functions, which take the same parameters, and have HRESULT return values, like the original IDocHostShowUI methods.
My classes also support IDocHostUIHandler2. This interface has only a single method which is called GetOverrideKeyPath( ), and it maps to the virtual OnGetOverrideKeyPath( ) function. Since this interface is provided with IE 5.5 and above, I have used preprocessor conditions so that if you build your application for any version of IE less than 5.5, the IDocHostUIHandler2-related code will not compile, and you don’t have the support (even if you override OnGetOverrideKeyPath( ) in your HTML view class). In order to compile your application for IE 5.5 and above, see my Windows Target Version Macros article.
The classes you’ll need when implementing IDocHostUIHandler are CDocHostSite, CDocHostOccManager, and CDocHostHtmlView. To use these classes, just copy the DocHostSite.h, DocHostSite.cpp, DocHostHtmlView.h, and DocHostHtmlView.cpp files into your application’s folder, add them to your project, and derive your HTML view class from CDocHostHtmlView instead of CHtmlView. To make sure it happens correctly, don’t forget to use the Find and Replace feature to replace CHtmlView with CDocHostHtmlView in both your header and implementation file for the HTML view class. By the way, whenever you want to port the code to MFC 7, just remove those four files, and change CDocHostHtmlView back to CHtmlView, and that would be all the actions necessary for performing the port. Clean, isn’t it?! Of course, remember that if you are using the IDocHostShowUI and/or IDocHostUIHandler2 support, you should watch out, because MFC 7 doesn’t have native support for them. In that case, just leave your code as it is with MFC 6, and compile it using Visual C++ .NET, you’ll see that my classes support MFC 7 as well, only in that case, they use their own implementation, and don’t rely on MFC’s implementation (however, all this is transparent to the programmer).
One other thing to note is that the only class you’ll have to work with directly is CDocHostHtmlView (of which you should derive your HTML view class). The rest of the classes do their job in the background, and you don’t have to mess with them at all, although they also need to be included in the project.
To customize the behavior of the Web Browser control, you have to override the virtual functions provided inside CDocHostHtmlView, and do what you need according to the documentation of the IDocHostUIHandler interface. For example, the sample application which can be downloaded at the bottom of this article disables the context menu by overriding the OnShowContextMenu( ) function which corresponds to the IDocHostUIHandler::ShowContextMenu( ) function.
All the virtual functions declared inside the CDocHostHtmlView have return types and parameters exactly identical to their corresponding IDocHostUIHandler, IDocHostShowUI, or IDocHostUIHandler2 functions. All of them except OnDocWindowActivate( ) and OnFrameWindowActivate( ) only have an "On" prefix in their names, and that’s the only difference with the signature of the corresponding IDocHostUIHandler functions. So, for example, to change the implementation of IDocHostUIHandler::GetExternal( ), you have to override the virtual function CDocHostHtmlView::OnGetExternal( ). Note that the sample application does not demonstrate the use of IDocHostUIHandler2 or IDocHostShowUI interfaces. For samples of customizing the behavior of these two interfaces, see the articles listed at the bottom of this article.
Here I will list some of the possible customizations applicable to this interface, and I will show you which function you need to override. It’s relatively straightforward to implement the functions if you read the IDocHostUIHandler documentations. Remember that even more customizations are possible, I’ll only list the commonly used ones.
To gain this feature…
… override this function of CDocHostHtmlView.
|Add/remove supported clip board formats for the WebBrowser control||OnFilterDataObject( ) [IDocHostUIHandler]|
|Accessing the host application’s methods from the script inside the web pages||OnGetExternal( ) [IDocHostUIHandler]|
|Disable the selection of texts in the forms||OnGetHostInfo( ) [IDocHostUIHandler]|
|Disable the 3D border||OnGetHostInfo( ) [IDocHostUIHandler]|
|Disable scroll bars||OnGetHostInfo( ) [IDocHostUIHandler]|
|Disable the execution of scripts inside the page||OnGetHostInfo( ) [IDocHostUIHandler]|
|Open links in new windows||OnGetHostInfo( ) [IDocHostUIHandler]|
|Flat scroll bars||OnGetHostInfo( ) [IDocHostUIHandler]|
|Enabling the auto complete feature inside forms||OnGetHostInfo( ) [IDocHostUIHandler]|
|Enable/disable the usage of Themes for the UI elements of the Web Browser control||OnGetHostInfo( ) [IDocHostUIHandler]|
|Changing the registry key under which the WebBrowser control reads the user settings from||OnGetOptionKeyPath( ) [IDocHostUIHandler]|
|Overriding the registry key under which the WebBrowser control reads the user settings from||OnGetOverrideKeyPath( ) [IDocHostUIHandler2]|
|Show custom context menus/disable context menus||OnShowContextMenu( ) [IDocHostUIHandler]|
|Override the accelerator keys for the Web Browser control||OnTranslateAccelerator( ) [IDocHostUIHandler]|
|Modify the URLs before loading them||OnTranslateUrl( ) [IDocHostUIHandler]|
|Show custom help files||OnShowHelp( ) [IDocHostShowUI]|
|Show custom message boxes||OnShowMessage( ) [IDocHostShowUI]|
I have provided a set of articles which demonstrate some of the customizations possible, and each of them comes with sample applications that actually do the customizing. Here is a list of them, in alphabetic order:
This article demonstrates three possible scenarios for customizing the WebBrowser’s context menu, sorted by the difficulty of implementation from easy to hard. For each scenario, it provides a sample application which demonstrates the necessary code for performing the customizations. It’s a must-read for those who are going to customize the WebBrowser control’s context menus.
This article demonstrates how to show custom message boxes instead of the message boxes being displayed by the WebBrowser control by default. The sample application for this article extracts the message box caption from a DLL string resource, and ensures that no message box with the caption "Microsoft Internet Explorer" are shown.
This article demonstrates how to make the WebBrowser control read its registry settings from the location you specify to it. This allows you to simply change some of the features of the WebBrowser control for your own application without touching the settings that the WebBrowser control uses for other applications. The sample application demonstrates how to change the default link colors for your application, and also define a hover color for the links.
This article shows how to extend the WebBrowser control’s DOM in your own applications. Using this method, you can provide a communication means between your application and HTML pages you display; such a communication is quite necessary for creating an application which uses the WebBrowser control to display its user interface. This communication is provided using a COM object. Major applications like Microsoft Outlook Express® (which comes with Internet Explorer®) and Microsoft Outlook® (which is a part of the Office® family) use the same technique for creating rich HTML user interfaces.
The CDocHostHtmlView class is now (2003/03/27) updated with a new fix submitted by Todd Perlmutter. This fixes a sizing issue with the WebBrowser control which is the result of some MFC code and results in the WebBrowser control’s scrollbars being clipped. The article’s download ZIP file contains the new class with the WM_SIZE handler Todd has added. Thanks, Todd!