Introduction
This article provides the base code for the development of a professional toolbar for Internet explorer.
While the other articles provide a good starter for toolbar concept, they still lack some bits that are needed for professional applications and supporting look & feel for Vista as well as XP along with complete setup.
This article is best suited for newcomers to toolbars that want to get a working project in 5 minutes.
I still recommend further reading in the related articles for those of you that want to get more thorough understanding about the internals of the BandObject component.
Background
While developing my Password Manager toolbar ,I started looking for code samples and articles in the Net. I found some very useful ones (like Pavel Zolnikov's article) that helped me a lot to start basic toolbar implementation.
But then I found some bits of problems such as :
- toolbar do not show in IE7
- toolbar problems in Vista and bad look & feel on Vista
- problems with the installation
- toolbar do not show after installation and more .....
Since I had to deal with all these problems in order to get it working professionally,I spent days to find out all the comments and forums that solve those issues.
I try here to provide the most "Clean" toolbar implementation for all of you guys ,beginners and experts , that want to experience the fun of creating toolbars without the plumbing hassles.
There are still some small issues remaining and I hope that with the help of some keen coders we can manage to solve all issues and provide the perfect Toolbar class.
Using the Code
Simply extend the Toolbar
class . you can rename it to whatever name you want.
I provided in the sample a simple button and label . it is a regular WinForm ToolStrip
so you can put here all ToolStrip items.
Accessing the Browser and DOM
Use the Explorer
property to access the WebBrowserClass
.I added for simplicity the Navigate(string url)
and NewWindow(string url)
methods.
The "Constants" class:
class Constants
{
public const string ToolbarName = "Sample Toolbar";
public const string ToolbarHelpText = "Sample Toolbar Help Text";
public const string ToolbarGUID = "4D02E7E6-5930-4b51-B9B0-9F21B3789400";
public const int ToolBarWidth = 160;
public const string Assembly = "Toolbar, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=f2e11770db40f5b0";
}
You MUST create a new GUID for your toolbar instead of the one supplied with oolbarGUID
.
It is advised to sign the released assembly with different .snk file (ToolbarKey.snk) . in that case the PublicKeyToken will be changed, so you will need to revise it in the Assembly
const string.
To extract the public key token from dll you can use sn -T from VS2005 tools.
Debugging , Rebuilding & Development
In order to debug the toolbar you can remove the remark from the constructor
public Toolbar()
{
......
Alternatively you can use the "Attach to Process" option of VS2005 IDE and attach to IE.
When you update the toolbar's code , you do not need to unistall and reinstall it ,you just need to re-register it in the GAC.
go to Start-->Setting-->Control Panel-->Administrative Tools
select "Microsoft .NET Framework 2.0 Configuration" .
right-click on the "Assebly Cache" , choose "Add" and add the toolbar dll.
Points of Interest
The use of BHO to show toolbar after installation
BHO (Browser Helper Object) is simmilar to Toolbar (BandObject) except of the GUI capabilities.
I use the BHO only for the purpose of showing the toolbar immediatly after installation.
At the setup I register the BandObject as BHO by adding it to the registry:
RegistryKey bhoKey = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft
\Windows\CurrentVersion\Explorer\Browser Helper Objects\" + guid);
bhoKey.SetValue("NoExplorer", 1, RegistryValueKind.DWord);
At first time the SetSite
method is called for the BHO object the ShowToolbar
method is called.
public virtual void SetSite(object pUnkSite)
{
if (pUnkSite is IInputObjectSite) {
_SetSite(pUnkSite);
}
else if (pUnkSite is InternetExplorer)
{
ShowToolBar(pUnkSite);
}
}
The ShowToolbar
is responsible to Show the toolbar using the ShowBrowserBar
method , and then remove the BHO from the registry since it have no use any more.
Registry.LocalMachine.DeleteSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion
\Explorer\Browser Helper Objects\{" + Constants.ToolbarGUID + "}");
Painting the toolbar's background according to the theme
When I first tested the toolbar on Vista I got it pretty ugly gray background instead of the smooth gradient style of IE7 of Vista. I digged to find a solution to this and found the fantastic "Geer's Blog" that gave me just the answer I was looking for.
The code snippet that is responsible to inherit the background of the toolbar looks like that :
[DllImport("uxtheme", ExactSpelling = true)]
public extern static Int32 DrawThemeParentBackground(IntPtr hWnd, IntPtr hdc,
ref Rectangle pRect);
protected override void OnPaintBackground(PaintEventArgs e)
{
if (this.BackColor == Color.Transparent)
{
IntPtr hdc = e.Graphics.GetHdc();
Rectangle rec = new Rectangle(e.ClipRectangle.Left, e.ClipRectangle.Top,
e.ClipRectangle.Width, e.ClipRectangle.Height);
DrawThemeParentBackground(this.Handle, hdc, ref rec);
e.Graphics.ReleaseHdc(hdc);
}
else
{
base.OnPaintBackground(e);
}
}
Toolbar location
I admit that I didn't get it perfect yet ,the ability to locate the toolbar everywhere I like.I had it working pretty good on XP but then found out that it do not work well on Vista. I also tried to remember the location of the toolbar by implementing IPersistStream
,but it didn't work.
Finally I comporized on a static toolbar and that works fine both in Vista & XP .
The flag in GetBandInfo that is responsible for the location and other layout behaviors is:
dbi.dwModeFlags = DBIMF.NORMAL | DBIMF.VARIABLEHEIGHT | DBIMF.ALWAYSGRIPPER;
Process Scope
All BandObjects that are created with "new window" or "new tab" are in the same process so you can use a static member in order to communicate between them.for convenience I added a static list of all the toolbars in the process: ToolbarsCollection
.
I used this collection in my Password Manager to synchronize login\logout and other operations between the toolbars.
Launching IE from the desktop or the quick-launch create new process so in that ase the collection won't work.
About the Setup
I used the very basic setup project provided by VS2005. Almost all the setup code that is responsible for registry operations : COM registration, BandObject registration & BHO registration is done in the ToolbarInstaller
calss which derives from System.Configuration.Install.Installer
Another thing I do in the setup is the registration in the GAC by explicitely selecting the GAC folder in the File System. I could register the toolbar in the GAC with code using the Publish
class. but this is out of the scope