I'll start by creating a simple addin step by step, and show you how to create a toolbar and add some buttons linked to functionality provided in the addin.
I'll use the builtin project template provided by VS2008. An alternative is to use the Visual Studio SDK, but this is not the scope of this article.
You start with File/New project, then choose Other Project Types, and finally choose the Visual Studio Add-in project template. Type the name of your addin you want to create, eg. MyAddin. This will start a wizard which will allow you to set some options on how the addin will be created.
The first option is to choose the Programming Language. I'll choose c# as language.
The next option, determines what applications will host your addin. The options available here, will depend on your installation, but basically there will be at least 2 options:
- Microsoft Visual Studio 2008
- Microsoft Visual Studio 2008 Macros
Next you need to give a name and description of the addin. I'll just name it MyAddin and as description MyAddin - VS2008 extension.
The next page of the wizard will ask you whether you want:
- to create command bar ui for your addin (it will create a tools menu item), so check this
- to load the addin when VS2008 starts ( we'll check this one also)
- if the addin will never put up modal ui (we'll leave this one unchecked)
Finally, you'll get a summary of all the options you've selected and you can finish the wizard.
When you'll look at the files created by the wizard, you'll find as most important files
- Connect.cs, which is the file we're going to work with most.
- MyAddin - For Testing.Addin which is a XML file
- MyAddin.Addin another XML file
- CommandBar.resx a resource file containing some language dependent resource strings.
Let's look at the code generated in connect.cs. First we'll look at the OnConnection method, and make some changes to it, so we can create our toolbar, instead of adding an menu item to the tools menu (the default created by the wizard).
The OnConnection is called when the addin is loaded. This will allow you to setup the addin and is also the place where our toolbar will be created. We'll remove the code marked by the dark yellow background, as we don't want to create a menu item in the tools menu. We'll replace it with code which will create our toolbar.
Replace the code with :
There are two ways to create toolbars, permanent toolbars and temporary toolbars. From what I've read in other blogs, mostly you'll use temporary toolbars, which are created when you're addin loads.
Now add the following code to the class Connect:
This code will create the toolbar for all commands you want to provide. As you will see next, I will store all available commands in a dictionary
Add a new class to the project, and call it ExtCommand.cs, which is defined as follows:
- The Name property will determine the name of the command used by VS2008 to call your addin.
- The Text property will determine the text of the toolbar button
- The Description property will show up as tooltip explaining what the command does.
- The Action property is a delegate returning a bool, linking the toolbar button to the code which you want to excute when the button is pressed.
As we create new commands in our addin, we'll add them to the dictionary (which is empty to start with).
We create now our first method, eg. SurroundWithBraces. This already exists in VS2008, but just to have a simple example, we'll create one ourselves.
This will take the current selected text and replace it with the same text, but surrounded with braces. Notice the try catch, which will ensure our addin will not cause VS2008 to crash.
Now we need to link the commandName to our private method. Create an entry in the dictionary for this command. Just add a dictionary entry as follows:
MyAddIn.Connect.Braces is the string which VS2008 will send as commandname parameter to the Exec method. Commandnames will alway start with MyAddIn.Connect follow by the name of your command. So if the name property of our ExtCommand object is Braces, the commandName will be MyAddIn.Connect.Braces. It's important that they are the same.
Next we have to change the QueryStatus method. This method will be called by VS2008 to query if a command with a specific commandName is supported by our addin. Initialy it uses an if structure, to compare the commandName to available commands, but because we've used a dictionary, the code can be replaced by:
We just have to check if the commandName exists in our dictionary, to determine if our addin supports the commandName VS2008 is querying. Any commands added to the dictionary will automatically be returned as supported.
Executing a command is done inside the Exec method, called by VS2008 when the user clicks a button on the toolbar. Again, initially, the code generated by VS2008 uses an if structure, to determine the method to execute. Our dictionary simplifies this code considerably:
_actions.ContainsKey, checks if the commandname exists in our dictionary. If this is true, we'll invoke the Action (a delegate to our private method), associated to the commandName (_actions[commandName].Action.Invoke()). It looks up the entry in the dictionary, returns the ExtCommand object. The Action property of our ExCommand object contains a delegate to our private method. Invoke just calls this method.
Almost there. We need to add another call to AddTemporaryUI() inside the method OnStartupComplete :
And finally, the OnDisconnection method has to be implemented, to remove our toolbar, when the addin is removed :
Adding additional commands, is very simple from here on... create a private method implementing the command. Add an entry to the dictionary and you're done. The rest is taken care of automatically. Remember the Name property of your ExtCommand object, will determine the commandName VS2008 will use. Just prefix it with MyAddin.Connect where the commandName is used as the key in the dictionary.
I want to give credit to Carlos J. Quintero (Microsoft MVP), who wrote an article Howto: adding buttons, commands and toolbars to Visual Studio .NET from an addin providing for the base of the AddTemporaryUI method. It's is certainly worth reading!!