KeyCommands


pianokeys.png

In Firefox you can set up command key-bindings in the XUL files of an add-on, and call back into the extensions Javascript. Internet Explorer doesn't have this pre-packaged support for adding key commands, so instead you have to catch the system key events, detect the combinations you're interested in and call the right functions manually.

There are different ways to do this, depending on what you need. Sven describes how to capture all key events in IE from a BHO, even if the focus is on the address bar. Looking at that made my head hurt, it needs some thread-local variables and mapping to remember which thread is associated with which document.

Luckily, I realized that my needs were a bit simpler. I'm happy to have my commands only work when the focus is on the document itself, which meant I could use the DOM event handlers exposed through IHTMLDocument2 to capture key events.

Attaching a C++ callback to an event handler in the MS DOM is not trivial, and involves some COM boilerplate, but I had a helper class I use to capture onclick events for elements. I'll cover that along with the rest of my DOM helper functions in a future post.

Reusing that, getting called when a key event occurred was quite easy, though one wrinkle I hit was that onkeypress doesn't get called for all keys, such as those produced when control is held down. I worked around this by synthesizing an equivalent using onkeydown/up, since they do get called for all keys.

One odd thing about these handlers in IE is that they don't get passed the event information directly as a parameter. Instead you have to ask the current window what the last event was, and pull the information from that. To get the current window, you have to ask the document, and to get the document, I had to query the browser, since that's all I store in my class, so the code is a bit verbose. It does the job thought, even if it is uglier than I'd like.

The next hurdle was working out the key codes for the events I was interested in. Here's what I found for the unusual keys I needed:

I then added a giant switch statement to handle all the key combinations I was interested in, and call the right functions. Once that was wired up, I also implemented saving the enabled state of the add-on in the registry, so users can turn it off when they're not using it, and it will still be off when they restart IE.