Creating an Internet Explorer Add-in Toolbar Button using C++ and ATL

Pete Brown - 22February2011

Just about every week, I put together the Windows Client
Developer Roundup. This consists of a bunch of links to posts that
deal with topics of interest to client developers. One of the more
time-consuming tasks in that work is simply copying and pasting the
link information into LiveWriter. When I open the URL in IE, I have
to manually copy the link and then, either copy and paste special
on the title (which is annoying, error prone, and includes a dialog
with a setting I have to choose each time), or because I type fast,
just retype the post title.

At the same time, I have to clean all the FeedBurner gunk off
the end of the URL, because links clicked in the roundup shouldn't
show up as towards FeedBurner traffic (that's a debate for another
time). An example FeedBurner URL with tracking looks like this:

It doesn't seem like a lot of work, but go ahead and click on
that link. Now, in the address bar, click and select just the
portion of the URL up to the question mark. Notice all the extra
clicking you have to do (or click, then home then move the cursor
etc.)? Do that 25 times and you see how it gets tedious.

I've been wanting to write an IE addin to copy and clean this
for me, but didn't get around to it until today. It took me almost
all day to write this add-in and this blog post, so blame this on
the Windows Client Developer Roundup being a day late this week
:)

Why did it take so long? I wanted to do this in C++, and my C++
is slightly more rusty than an old tractor left in the back field
for most of the century.

Now, you can actually accomplish creating a basic add-in simply
by storing a little hunk of script on the drive and adding the
right registry keys. However, I specifically wanted to do this in
C++. No, not because I hate myself, but because I'm starting to see
a resurgence of interest in C++. You can create add-ins using .NET
and Script, but both have significant limitations as well as
performance concerns. If you want to write an add-in of any
complexity, you'll almost certainly want to write it in C++. So,
that's what I decided to do.

These two articles were absolutely required reading to figure
out how to do this add-in.

Now, on to the project. I used Visual C++ inside Visual Studio
2010 for this project. I also used Internet Explorer 8 on Windows
7.

Project Setup

Visual C++ projects are typically created using wizards. Create
a new ATL Project using the ATL Project wizard.

Make sure you check off "Allow merging of proxy/stub code" or
you'll get compile errors. Also ensure you're creating a DLL.

Create the Add-in Class

Next, we'll need to create a class in our project which will be
used to expose the functionality of the toolbar button. For that,
we'll use the ATL Simple Object wizard.

I called the class BlogUrlSnaggerAddIn. Everything else, except
the ProgID, was filled in for me. Leave that blank.

Leave the next page with the default (disabled) values. The
final page lets you set some of the options. Be sure to select
IObjectWithSite so you can work with IE. I also changed
"Aggregation" to "No" like the MSDN example.

Now, without changing anything, build the project. What? You got
a bunch of errors because the component couldn't be registered?
Ahh, you'll need to exit Visual Studio then run it as Administrator
or enable per-user redirection. To enable per-user redirection,
right-click the main project and select properties. Then view the
Linker General property page. The setting is there; change it to
"Yes". (don't do this now, see note below)

Unfortunately, the registration we'll be using won't support
that, so while it will get you past the initial compile,
the later rgs additions will require that you run in
administrator mode.

So, once you exit Visual Studio and re-start in Administrator
mode, you'll be able to rebuild and have a base project with no
errors.

Adding in IOleCommandTarget Declarations

As the MSDN document instructs us, we'll need to add in
references to a couple header files (shlguid and mshtml) as well as
add support for the IOleCommandTarget interface. I love that I get
intellisense on the include files.

I've highlighted the new lines in the BlogUrlSnaggerAddIn.h file
snippet above.

IObjectWithSite and IOleCommandTarget

Right after the "END_COM_MAP()" statement in the .h file, add in
the following code to define the interface methods for
IObjectWithSite and IOleCommandTarget (I copied this right out of
the MSDN article)

If you leave out the final "public", this will mess up the scope
used in the DECLARE_PROTECT_FINAL_CONSTRUCT macro, so make
sure you add the "public" at the end of the code
above.

Next, we'll actually implement the code for the SetSite method
we added to the .h file.

Storing the Browser Reference using SetSite

The next hunk of code we need to add is to the
BlogUrlSnaggerAddIn.cpp file. It implements the SetSite method to
grab an instance of the browser for us to use in the other methods.
This is primarily copied from the MSDN example, with the class name
changed.

There's another GUID for the IDispatch interface which is also
useful. However, both are pre-populated for us in the .rgs file
we'll need to edit (I just wanted you to see one place where they
are defined -- they're also duplicated in the .IDL file, and code
in hex form in the _i.c file. Ugh)

Crack open the BlogUrlSnaggerAddIn.rgs file in the ResourceFiles
folder. You'll see it has been pre-populated with the class name
and the main CLSID and the TypeLib CLSID. Excellent. Now we need to
modify that to be appropriate to our class. Don't simply
cut and paste my code below, these GUIDs are Mine MINE! Get your
own stinkin' GUIDs!

This block is in addition to the registration block already in
the rgs file; don't replace the old one with this one, simply add
this one below it. Also keep in mind that all those NoRemove
statements are pretty darn important. You don't want to hose your
registry when playing with this little project.

There must be some way to resolve that Icon and HotIcon to the
runtime installation folder. I'm not sure what it is, though.
If you know, please tell me in the comments
below.

Finally, go into the .rc file and change the CompanyName,
FileDescription, LegalCopyright, and ProductName to something that
makes sense.

Phew! That's it for the setup.

Adding in Test Functionality

Much like Eli did in his post, I'm going to do a simple "Hello
World" test before I try to implement the real functionality. In
classic first-timer fashion, this is going to simply display a
message box that says "Hello World!". Crack open that add-in .cpp
file again and modify the Exec method so it includes a call to
MessageBox as shown here

Excellent! That's exactly what I was looking for. The next step
is to copy it to the clipboard.

Copying to the Clipboard

I want to copy both the page URL and the page title to the
clipboard. The natural choice for
format here is HTML. It took me a bit of piecing together from
various examples I found in searching. I also happened
upon a better way to handle BSTR instances, without worrying
about managing their allocation. Finally, I figured out what string
type to use for regular string manipulation: ATL::CString.
Using that requires adding a #include <atlstr.h> to
the top of your BlogUrlShaggerAddIn.h file.

That's a lot of code. However, because I'm inefficient with C++,
it should be reasonably easy to follow :) . Here's what's going
on:

First, I get the URL and Title from IE

Next, I register the HTML Clipboard format using the known
"HTML Format" string

Then, using some ugly string replace code, I create the
properly formatted clipboard data. Note that HTML written to the
clipboard needs to follow a format that includes context: typically
a valid HTML doc, even when you're just pasting a little link.

Once I have all that ugly string replace done, I put the string
into global memory

Once in global memory, I open the clipboard with an hWnd of 0
to allow anyone to get at the data

I then empty the current contents (how rude!), add the new
data, close the clipboard and return Success.

Now if you run it, you should be able to click the toolbar
button and get the title and URL pasted into LiveWriter (or Word or
whatever).

Cleaning up the URL

Ok, now that copy & paste works, it's time to do the
cleaning. Here's a reminder of what FeedBurner URLs with tracking
look like:

What I need to do is get rid of anything following utm_source up
to the next ampersand or end of string. Then the same with
utm_medium and utm_campaign. I'd just as soon get rid of everything
after the ? but that will break a few blogs that don't yet use
SEO-friendly URLs. I also don't want to be dependent on the
specific order of those parameters.

To help, I added an additional private function to the class. In
the .h, I added:

CString RemoveParameter(CString url, CString parameter);

Then in the class itself, I modified the Exec function and added
the implementation of the new function.

That's it! It's all working. I tested it with additional
parameters and validated that it didn't screw them up. Of course, I
may still have to do some slight cleaning of URLs for cases when
people (like me) put the site name in the title), but otherwise
this should save me a good bit of work every week. Plus, I learned
a little C++ along the way. Win!

Keep in mind, I'm relearning C++. If I did something
dumb, don't hesitate to (nicely) point it out in the comments,
especially if it's something other people shouldn't repeat in their
own code.

(note: this was all tested using 32bit IE8 on Win7 x64: Works On
My Machine)

I would suggest though to do registration once and then turn off the self-registration and run VS as regular user. The main reason is that if VS is running as administrator and you're launching IE to debug your add-in, IE will be running as admin too. When IE runs as admin, it disables protected mode, so you are debugging your code under different conditions from the ones it'll be running in everyday use.

While this does not have much impact on your specific scenario, it is important when accessing the registry or the file system, or when launching external processes.

This prevents :
* using the unsafe version of strcpy to avoid potential buffer overrun (welcome back to native world, again ;-) )
* remove the '+ 4' suspicious operation when computing the length of the buffer.

3. In RemoveParameter method, you should handle properly the case the given parameter is not found in the URL (even if it works in release mode, you reach an assertion in debug mode) :

Constructive criticism is always welcome. I made it pretty clear in this article that I haven't coded in C++ in a very long time. Your comment was not constructive. In fact, it points to one of the things that has given C++ a bad rap: people who think being douches to noobs is somehow advancing the art.

I *kind of* agree with Joe's point, but that's not really a criticism, more a statement of fact. You need to jump through a lot of hoops to write an IE plugin, and outside of that, there's really not a lot of actual logic to be written in just C++.

The only real "plain C++" logic I can see is really the CString bits, and for those, you'd typically prefer the standard library `std::string` class instead. (In general, prefer the standard library over MFC). For the string building specifically, `std::stringstream` might be a good bet.

Everything else is tied up in some horrendously ugly Microsoft APIs that you probably can't really avoid in this case.

As for `strcopy` ( in the few cases where you *have* to work with C-style strings, of course, rather than using the std lib string class), consider replacing it with `std::copy` (takes two iterators/pointers delimiting the string) or `std::copy_n` (takes an iterator pointing to the beginning of the string, and the number of chars to copy). That's another good rule of thumb, prefer the C++ std lib over the C std lib.

The "better way of handling BSTR", btw, is a special case of the RAII (Resource Acquisition Is Initialization) idiom, which is hugely important in modern C++, and you should implement it yourself pretty much whenever you're forced to deal with memory management.

In short, instead of writing code to "allocate memory, use object, deallocate memory", write a small wrapper object which, in the constructor, allocates the necessary memory, and in the destructor, frees it. Then you can create an instance of that object on the stack, and it will *automatically* clean up after itself (and even if an exception is thrown, destructors are still called so even then, you won't leak memory, saving you a lot of error-handling boilerplate code)

That's basically what CComBSTR does for you.

The same pattern can (should) be generalized to any other resource acquisition. For example, opening/closing the clipboard could be encapsulated in a small RAII wrapper class, wich, on construction, opens it, and on destruction closes the clipboard again.

Then your clipboard code could be replaced by something like this:

scoped_clipboard cp; // implicitly opensand clears the clipboard
::SetClipboardData(CF_HTML, hClipboardData); // could wrap this in a member function on scoped_clipboard if we want to

and you would be guaranteed that however you leave the function, the clipboard gets cleanly closed again.

Similarly for GlobalLock/GlobalUnlock: you want to be sure that your lock is released, so rather than relying on a manual Unlock call, write a small helper class which unlocks on destruction. (And then put an extra pair of { }'s around its use to force it to go out of scope immediately, rather than at the end of the function).

Of course, for quick 'n dirty code like this, doing it your way is no big deal, but in general, you should always use RAII to wrap your resource allocations, whether the resource in question is a file handle, a lock of some sort, a memory allocation or anything else. If it has to be acquired and released, or opened and closed, or locked and unlocked, it calls for RAII.

Great blog post, Pete! Thanks for sharing.
And thanks for remembering us that we should use the right tools for the task at hand: for some tasks C# is fine, for other ones C++ should be used.

I'd like to point you a small improvment you could do in your code.
When you use string literals with CString, you should always use _T("...") or L"..." decorations.
Use _T() for both Unicode and ANSI/MBCS backward compatibility, and use L"..." for Unicode only builds (which should be the default these days).

I noted that you correctly used _T("...") in several cases, but you missed some places, e.g.: CString("Version:0.9\r\n"), this should be CString(_T("Version:0.9\r\n")) or CString(L"Version:0.9\r\n").

I know it compiles and works for you, but this is because of an (IMHO, "evil") CString implicit constructor, which takes an ANSI/MBCS string and concerts it to Unicode. I think this is a waste of CPU cycles, because there are useless calls to MultiByteToWideChar for a string literal that should be Unicode L"..." in the first place.
(In some cases this behaviour could lead also to ugly bugs, but not when you have pure ASCII text like this.)

To avoid these implicit CString constructors, you can #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS in your "StdAfx.h" precompiled header file.

>>> The only real "plain C++" logic I can see is really the CString bits, and for those, you'd typically prefer the standard library `std::string` class instead. (In general, prefer the standard library over MFC).

While I agree that STL containers are better than MFC ones, I think CString is much better than STL std::[w]string.
CString offers a richer public interface, it's better integrated in Win32 programming environment than STL string, it can easily load strings from resources (good for internationalization), etc.

Note that it is possible to use the quality STL containers (like std::vector, std::map...), with the quality ATL/MFC CString class.

@CppJohn: CString definitely has better Win32 integration, but std::string has better standard library integration (and on a related note, CString implies a third-party dependency which could be avoided). As you say, the right tool for the job. I'm not a huge fan of CString though.

However, I'm curious, apart from the Win32/resource stuff, what do you feel is missing in std::string's interface?

@jalf:
>>> However, I'm curious, apart from the Win32/resource stuff, what do you feel is missing in std::string's interface?

The Win32 integration and resource loading stuff are sufficient to me for using CString in Win32 ATL/MFC C++ code (of course, if I have to write multiplatform C++ code, std::[w]string is a natural choice).

There is a CString constructor overload that comes in handy when you need to load string resources.

GetBuffer() is another convenient method of CString, useful for Win32 API's that need a writable buffer.

CString::FormatMessage() is another useful method lacking in STL strings. (With FormatMessage() you can specify the order of parameters in the format string, it is more powerful than simple printf()-like formatting.)

There are also other convenient methods like CompareNoCase(), Trim(), Left(), Right(), Mid(), Tokenize(), etc. available in CString but not in STL string.

The implicit cast is missing from `std::string` because it's a bad idea. Implicit conversions in general cause more trouble than they're worth.

Case insensitive compare and FormatMessage and tokenize are all good points (although Boost gives you the same (in portable implementations, of course), if you're willing to take dependencies on external libraries anyway)

Most of the others are there already:
Left(N): std::string(str.begin(), str.begin() + N)
Right(N): std::string(str.end(), str.en() - N)
Mid(N. M): std::string(str.begin() + N, str.begin() + M)
GetBuffer(): str.begin() (or, if you need a pointer, rather than an iterator, &*str.begin() or &str[0]

Of course, you're right about the Win32/resource handling stuff. I just wanted to point out that std::string is nowhere near as crippled as you make it out to be.

I know it's doable with proper combinations of string::begin() and end() and doing some math, but the point is that having methods like Left(), Right() and Mid() available increases the semantic level and the readability of the code.

In all honesty, in the middle of a C++ code, what do you find more readable? A simple call to CString.Left(N) method, or an expression like std::string(str.begin(), str.begin() + N)? :)
I think the brain parses "CString.Left(N)" in a faster and easier way.

> GetBuffer(): str.begin() (or, if you need a pointer,
> rather than an iterator, &*str.begin() or &str[0]

There is a subtle difference here between CString and std::string: the STL strings do not interoperate well with legacy C code (like Win32 API's), because STL strings are in general not NUL-terminated strings, e.g.

> I know it's doable with proper combinations of string::begin() and end() and doing some math
You mean by using the same two functions in every case, and by "math", you mean "using the same N that you'd be using in the CString version"?

Really, I don't see much "math" in the STL string version either.

> In all honesty, in the middle of a C++ code, what do you find more readable? A simple call to CString.Left(N) method, or an expression like std::string(str.begin(), str.begin() + N)?

Honestly? The latter. The former doesn't really tell me much. Does it mean "take the N'th character from the left", or "take N characters starting from the left", or "are there N characters left"? "Mid" is even worse, because it doesn't actually operate *from the middle*. You actually have to go and look it up if you don't know off-hand what it does.

But the std::string version is pretty easily readable, I'd say.
"Call the string constructor, and pass to it the range of characters that starts with the beginning of str, and ends N characters from the beginning."

And I consider it a bonus that the *same* interface is used for so many other operations. No matter what you want to do with the string, it's going to look much like this, working on a pair of iterators, which means that there are fewer functions you need to understand, and you're going to encounter the same names more often.

I think an interface is more readable if it is compact and reusable. If I have to use a different function for every subtly different task, then it's a pain to keep track of. But if the interface contains one or two simple, generic tools which can be used to solve *all* the tasks, then it's easy to remember and much more readable IMO.

As for the null termination, I think it cuts both ways. Remember how wonderfully inconsistent the Win32 API is. Half the functions will write a null-terminated string into the buffer, the other half won't write the terminating null. So half of the API will work naturally with CString, half would result in a buffer overrun with CString, but work safely with the STL string. ;)

But of course, it's just a matter of habit. I'm just more used to seeing the `std::string` version.

In any case, it's hardly a big deal. If there's one constant in C++ development then it's that there's never just one string class. ;) (and that they're all flawed in some way, unfortunately)

hi
Thank you for this article.Excuse me,I do not speak English well.
please help me.I Built the above project ,but I want create a standard toolbar for Internet Explorer.
a example is this:
http://www.codeproject.com/KB/wtl/rssreaderplugin.aspx
i do understand no thing from this project . Can you guide me?
If possible Teach me With Image help.

here, we place one Icon on the Command bar of a IE....Now I want to add my custom Toolbar on IE instead of one icon on Command bar...so for that what can I do? you can provide me any link for this also....

some truly great content on this web site , thankyou for contribution.

Comment on this Post

Name (required)

Email address (will not be published) (required)

Website url

Remember me

Your comment is being submitted, please wait...

Your comment has been posted, thank you. (If your comment does not appear shortly, it was marked as spam.)

Pete Brown is a XAML and Blinky lights guy at Microsoft who focuses on Windows XAML (WinRT), WPF, Silverlight, .NET Micro Framework and other "code on the client" and "code on a device" technologies. This is his personal blog.
About Pete/Full Bio | Contact | About 10rem.net