IE7 Advanced toolbar buttons
February 24, 2007 on 3:47 pm | In Uncategorized |Currently, there are several ways to create addons for Internet Explorer. The two I’ll be talking about in this post are BHOs (Browser Helper Objects) and Toolbar Buttons. To create a toolbar button, you simply add a value into the registry specifying whether you want to either launch a script, a function inside a COM library, executable or open an Explorer Toolband. When writing an advanced addon, most of the time you’d probably want to use a COM object.
As described in the Toolbar Button MSDN article, it’s fairly easy to get the COM object’s IOleCommandTarget::Exec function called when the user clicks the toolbar button. However, this method limits you to basic toolbar buttons. What if you’d like to create more advanced toolbar buttons, one with a dropdown menu for example?
This is a problem I ran into during the development of the first version of the Mapper IE7 addon. I’ve also seen this question being asked a few times at the IE Extension Development MSDN Forums. Several solutions to the problem are available on the internet (like this Codeproject article, or this newsgroup discussion). However, none of the solutions I found adds a real dropdown button into the toolbar, what I actually wanted to do.
My solution to the problem involves window subclassing. We basically need to hook into the toolbar’s WndProc to change its behavior. We also need to hook the toolbar’s parent window WndProc to listen for parent notifications such as WM_COMMAND messages. To set up these hooks, we need the hWnd of both windows. Functions to find these hWnds should be fairly easy to implement using Spy++ and the FindWindowEx function.
Note that since we’re adding the button to the toolbar from our code, we don’t need to add a Toolbar Button using the registry keys like the official API tells us to. Instead, we’re going to create a BHO. Since Mapper was written in C#, that’s what I used for the code attached to this article as well. There are several articles on the internet describing how to write a BHO in C#.
Let’s describe what we need to implement when we want to accomplish our goal. First, we need to set up the hooks in the BHO’s constructor. Next, we’ll need to listen for two different messages: TB_ADDBUTTONS and TBN_GETBUTTONINFO. The first one gets send to the toolbar itself, the second to its parent. It’s important to listen to both messages, because TB_ADDBUTTONS is important when the user customizes/resets the toolbar. TBN_GETBUTTONINFO should be getting called every time we start up Internet Explorer, but also when the user customizes the toolbar. When either of these functions gets called, we add our own button (or button info).
If you’d like to add your own image to the button (which you probably do), you also need to listen for TB_SETIMAGELIST. This way you can add your own icon into the toolbar’s image list. It has already been done in the attached code.
After the button has been successfully added we need to listen for user input. Obviously, we do this by listening for the WM_COMMAND and TBN_DROPDOWN messages. When the toolbar’s parent receives the TBN_DROPDOWN message, it’s time for us to show the drop down menu. You can do this using TrackPopupMenuEx (I did not include the code to do this though). Then you’ll receive WM_COMMAND messages when the user clicks any of your menu items.
Last but not least, we need to make sure we unsubclass the windows when our BHO unloads. Unfortunately, we can’t do this in the BHOs destructor. It seems that the destructor doesn’t always gets called. I think this has to do with .NET objects exposed as COM. Luckily, we can listen to WM_NCDESTROY, and remove the subclass there.
The basics of the hooking / message listening part are all done for you in the attached file. I didn’t do any BHO registering or COM stuff, since there are plenty of tutorials on that. If you’re familiar with Win32 programming, you should have no problem understanding what happens.
Download BHO.cs
Tags: addons, BHO, COM, dropdown, IE7, internet explorer, mapper
7 Comments »
RSS feed for comments on this post. TrackBack URI
Leave a comment
Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds.
Valid XHTML and CSS. ^Top^


Not a C# developer (yet) but I found your example and explanations exceedingly easy to follow and understand. It will certainly encourage developers and administrators to take advantage of IE’s extensibility.
Regards.
Comment by Rob — February 25, 2007 #
Neat trick. It’s pretty likely to break in future versions of IE, but it’s an interesting approach for now.
It’s probably worthwhile to explain how to get the .NET BHO loaded in IE; this isn’t trivial to do today.
Comment by Eric — February 28, 2007 #
Thanks! There’s a good example of a C# BHO over at the codeproject, but I might write an article on this as well. I realize this way of extending the browser depends on the way the browser is built at this moment, so it is indeed possible to break in the future (especially the functions to obtain the hwnd).
One thing I didn’t mention is that in this way you can also add your button at other positions in the browser. For example near the favorites buttons or next to the zoom button.
Comment by yousef — February 28, 2007 #
Well written and explained. I was amazed at the power of C# for this application. Very little code for such alot of functionality.
Comment by Rob — September 3, 2007 #
I see that there are declares for comctl32.dll api’s. Be aware that Vista does not include this library. The next step after writing an addon is testing and then deployment. I have found the later step to be the hardest of them all.
Comment by Rob — September 3, 2007 #
Hi Youssef,
I implemented the code as you described above, but there seems to be a flaw. The button only shows up on the drop down list after clicking the chevron, and not in the main toolbar. Strange, is it not? Perhaps the number of items in the internet explorer count of toolbar items does not match the actual toolbar items because a rogue item was inserted? What do you think? Any chance of making the full source code available?
Comment by Mark — September 9, 2007 #
Hi, i was interested in implementing this functionality for myself and found your website which is very insightful. I’m trying to convert it to C++ which doesn’t seem to complicated (thanks for the well laid out code) but i’m struggling with the message bits.
You aren’t entirely clear on what windows i need to be subclassing. From some invesigation work, i’m assuming the toolbar window is of class type “ToolbarWindow32″ and i’ve guessed its direct parent window is the “parent”. However, i don’t get the TB_ADDBUTTONS message or the TBN_GETBUTTONINFO message so my button is never added to the window.
Any suggestions
Thanks
Comment by John — October 22, 2007 #