Checklist for Embedded IE
August 23, 2006 7:13 pm AJAX, C/C++, DOM, ECMA / Javascript, Internet Explorer, Programming, Tools and Libraries, Tutorials, Web and Web StandardsMSHTML is an awesome user interface tool, but it has a whole lot of standard behaviors, many of which aren’t what one wants for an application (since it’s designed for the web.) This is a list of stuff you need to do to embed IE COM and have it behave like a normal application. There’s more than a person might expect.
- Suppress the user interface. IE starts with most of its interface turned off, but a few things aren’t. Notable things to include are to suppress the context menu and keyboard navigation.
- There are several ways to suppress the context menu. The easiest way is to do it in the html. Add oncontextmenu=”return false;” to your <body> and the problem just goes away, and it’s easily manually overridden for specific elements later.
- Alternately, you can override the interface programmatically through IDocHostUIHandler.
- Get rid of the OnNavigate noise (the clicking sound when you hit a link.) This is harder than it should be.
- Prevent keyboard navigation. If you only ever navigate once, and then do everything else in DHTML, this isn’t an issue, because there’s nothing to go forward or back to. However, if you need to, the way to do this is to capture DWebBrowserEvents2::BeforeNavigate2() and fill its last parameter, VARIANT_BOOL*& Cancel, to true. For security reasons this can’t be done in HTML without a garish ugly dialog box confirmation.
- Prevent dragging and dropping links. Do this with BeforeNavigate2() just like keyboard navigation.
- Prevent selection. The easiest way to do that is in the HTML by adding onselectstart=”return false;” to the <body>, which is also easily overridden for child elements where appropriate. If you need it programmatically, such as a block which can be turned from and to editability, that’s in IDocHostUIHandler.
- Handle some keys directly. Particularly often, control keys, tab and f-keys need very different interpretations in applications than are the defaults in IE. Some keys can be reliably intercepted in JScript, but not all of them. For lightweight stuff, use JScript; it’ll be less painful. However, if you need real control, you need to provide an IDocHostUIHandler::TranslateAccelerator() implementation.
- Suppress the interior border. People are often surprised that they turn off the window border in IE, and yet it seems to still appear. That’s because IE’s default stylesheet puts an inset bevel on every web page. Turn that off in CSS by writing body { border: 0; }.
- Begin to embed your images and other support media as resources, and access them with the res:// protocol.
- One ugly caveat: I have never found any variation of the DirectX PNG alpha filter hack which works with res://, and I’ve looked often and at some very weird variations. It is my current belief that a PNG cannot be embedded through res:// and still be fixed for alpha. This leads to the unfortunate case of requiring at least part of your resources on disk. If anyone knows a way around this, a heads-up would be greatly appreciated.
- Set up a system to exchange messages between IE DOM/DHTML/JScript and your application. There are a bujillion ways to do this, but I tend to use a combination of intercepted element events (mostly OnClick in WebBrowserEvents Invoke,) DOM extension behaviors that allow me to call C++ directly from JScript through IDocHostUIHandler::GetExternal(), and executing scripts directly on the DOM object through IHTMLWindow2::execScript().
- Build everything in the to be inside a container; make the body itself overflow: none. This prevents several ugly re-layout quirks which we’re used to on the web but not in applications, when content gets long.
- Start the container invisible, and make the black. That way, during the lag while resources are being loaded, you have a reasonable appearance. Black flashes look correct. White flashes look broken.
- Set an onload=”HandleLoad();” function for the <body>. That way, you know when all resources are loaded, and thus when it’s safe to take the invisible clause off of the main container.
- Set the main container position:relative, to make absolute positioning of contained elements easier.
- Build your web page in as a resource, and load it through IHtmlDocument2::write(). This allows you to load a document at runtime without using about:blank (which most people use, but which causes a brief white flash before your application loads; very unprofessional looking.) You’ll need SafeArrayAccessData() and SafeArrayUnaccessData() to use write() safely. When it comes time to skin or internationalize, and when you’re dealing with a compile cycle which is just linking, you’ll thank me for this.
- Suppress dragging on links and buttons. If you don’t, people will be able to drag them outside the app and onto the desktop as shortcuts, and when followed those shortcuts will lead into your HTML page from the outside (which is, surprisingly, legal.)
- Consider compressing your executable, such as with UPX, which makes resources unreadable externally.
- Set an id on your <body>. The is considered the origin of most events which don’t have a clear origin, and that means that catching these events is a lot easier (catching by id is the most straightforward way to sort out sources.)
- Resist the urge to use runtime styles. They’re not worth the problems they cause.
That should get the new IE user through some common foibles. I’ve probably missed stuff; if you can think of something, lemme know. I do not currently know of a way to embed flash, unfortunately, without leaving available an extra file.

August 23rd, 2006 at 8:46 pm
[...] Source: FatBlogread more | digg story [...]
April 28th, 2008 at 8:52 am
Any idea on how to prevent cursor changes while navigating? It drives me crazy in my app that whenever I navigate to a new topic, the cursor flashes busy briefly.