Internet Explorer

To embed Internet Explorer into our container window we use the IWebBrowser2 ActiveX control which is installed with Windows XP onwards. By default, the control emulates Internet Explorer 7, but we can set a registry key to modify this behaviour to make it emulate Internet Explorer 11.

We'll put all our code in a CWebBrowser derived class called CInternetExplorer, with implementations of the four pure virtual functions to make the class concrete.

Creating the Browser Control

We begin in the CreateBrowserWindow function by setting version 11 emulation. I have achieved this by setting a registry key under HKEY_CURRENT_USER, but you can define the key under HKEY_LOCAL_MACHINE, which is probably the way I would do it from an installer, so that the same emulation would happen for all users. The key name must match the executable name and if all works correctly you should see the following entry in the Registry Editor.


Next we need to create a hierarchy of windows beneath the container, eventually creating a host window. We create a sink site to connect our class to the browser to receive events, which at this stage is used to determine when an HTML document has been loaded, and then we create the browser instance using the program identifier "Shell.Explorer". If all this succeeds, we will be able to retrieve the IWebBrowser2 instance.

Finally, because this is Internet Explorer, which doesn't get much love from web programmers these days, I made a call to IWebBrowser2::put_silent to disable script error popups. This is completely optional and in our case we would develop a user interface code to work without script errors, so we will remove this call later.

Navigate, Refresh and RunMessageLoop Functions

The remaining three functions we need to define are easy by comparison to what has gone before. The Navigate function calls IWebBrowser2::Navigate, the Refresh function calls IWebBrowser2::Refresh2 and the message loop is pretty much standard Windows fare with one exception; we must get the in-place active object from our IWebBrowser2 instance and call its TranslateAccelerator function on a key down event, otherwise certain keys such as DEL don't work.

The final pieces in the jigsaw are to add message handlers for WM_DESTROY and WM_ERASEBKGND and a sink entry for DISPID_DOCUMENTCOMPLETE, which at this stage will make the browser window visible when the HTML document has been completely loaded. If all goes well, you should see something like this:

One thing to note is that this site generates lots of script errors which you can see in the Output window when running under the debugger. To get around this you can set the debugger type to "Managed Only" in Configuration Properties/Debugging for the Visual Studio project. However, the goal of this series is to write our own HTML and JavaScript, so we want to ensure that script errors are logged when we reach that stage.