HOWTO: Adding buttons, commandbars and toolbars to Visual Studio .NET from an add-in

Author:

Carlos Quintero MVP

COMMUNITY SOLUTIONS CONTENT DISCLAIMER

MICROSOFT CORPORATION AND/OR ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY, RELIABILITY, OR ACCURACY OF THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN. ALL SUCH INFORMATION AND RELATED GRAPHICS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THIS INFORMATION AND RELATED GRAPHICS, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, WORKMANLIKE EFFORT, TITLE AND NON-INFRINGEMENT. YOU SPECIFICALLY AGREE THAT IN NO EVENT SHALL MICROSOFT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, PUNITIVE, INCIDENTAL, SPECIAL, CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF USE, DATA OR PROFITS, ARISING OUT OF OR IN ANY WAY CONNECTED WITH THE USE OF OR INABILITY TO USE THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN, WHETHER BASED ON CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY OR OTHERWISE, EVEN IF MICROSOFT OR ANY OF ITS SUPPLIERS HAS BEEN ADVISED OF THE POSSIBILITY OF DAMAGES.

SUMMARY

This article provides a code sample to add buttons, commandbars and toolbars to the Visual Studio .NET IDE from an add-in.

SYMPTOMS

This article provides a code sample to add buttons, commandbars and toolbars to the Visual Studio .NET IDE from an add-in.

MORE INFORMATION

Visual Studio .NET allows add-ins to add commandbars of 2 kinds:
 
- Permanent commandbars: these commandbars remain visible in the IDE even if the add-in is unloaded through the Add-in Manager. The rationale for this behavior is to optimize the startup of the IDE and add-ins: the commandbars are created faster if they are persisted and retrieved from disk than if an add-in have to create them and add all its buttons by code when the add-in is loaded. So, add-ins create these commandbars only once (when the OnConnection method receives the value ext_cm_UISetup in the connectMode parameter) using the DTE.Commands.AddCommandBar() function and they are removed only when the add-in is uninstalled (not when it is unloaded) through a custom action in the uninstaller using the using the DTE.Commands.RemoveCommandBar() function. Since this behavior will be confusing for many users, most add-ins don't use this approach.
 
- Temporary commandbars: these commandbars are created each time that the add-in is loaded using the DTE.CommandBars.Add() or CommandBar.Controls.Add() functions (depending on the type of commandbar: Toolbar or CommandBarPopup) and they are removed by the add-in each time it is unloaded, using the CommandBar.Delete() method. This is the kind of commandbars used in this article.
 
In any case, controls (buttons) are added to a CommandBar using Command.AddControl(commandBar). This function returns a CommandBarControl, which has properties to set the Caption, etc. Some properties, though, will require to cast it to a CommandBarButton, for example to set the BeginGroup or the Style (msoButtonIcon, msoButtonIconAndCaption, etc.) properties. The status of a CommandBarControl (visible, enabled, etc.) is controlled through its underlying Command, in the implementation of the IDTCommandTarget.QueryStatus method, not through the properties of CommandBarControl.
 
Note: there are a couple of bugs in the VS.NET IDE that cause a reload of an add-in after being unloaded if it has added a CommandBarControl to some built-in commandbar of the IDE (such as the "Tools" menu) and another add-ins has done the same, or if it has created a toolbar which is on the same row that the toolbar of other add-in (see the References section below).
 
The following source code (VB.NET) shows an add-in that creates an EnvDTE.Command and exposes it in the Visual Studio .NET IDE through the following UI elements:
 
- A button on the "Standard" toolbar of VS.NET.
- A menu entry on the "Tools" menu of VS.NET.
- A menu entry on the context menu of a code window.
- A new menu on the main menu of VS.NET
- A new toolbar.
 
Public Class Connect
   Implements Extensibility.IDTExtensibility2
   Implements IDTCommandTarget
 
   Private Const MY_COMMAND_NAME As String = "MyCommand"
 
   Private applicationObject As EnvDTE.DTE
   Private addInInstance As EnvDTE.AddIn
   Private myStandardCommandBarControl As CommandBarControl
   Private myToolsCommandBarControl As CommandBarControl
   Private myCodeWindowCommandBarControl As CommandBarControl
   Private myTemporaryToolbar As CommandBar
   Private myTemporaryCommandBarPopup As CommandBarPopup
 
   Public Sub OnConnection(ByVal application As Object, ByVal connectMode _
      As Extensibility.ext_ConnectMode, ByVal addInInst As Object, _
      ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
 
      Dim myCommand As Command
      Dim standardCommandBar As CommandBar
      Dim menuCommandBar As CommandBar
      Dim toolsCommandBar As CommandBar
      Dim codeCommandBar As CommandBar
      Dim toolsCommandBarControl As CommandBarControl
      Dim myCommandBarButton As CommandBarButton
      Dim position As Integer
 
      Try
 
         applicationObject = CType(application, EnvDTE.DTE)
         addInInstance = CType(addInInst, EnvDTE.AddIn)
 
         Select Case connectMode
 
            Case ext_ConnectMode.ext_cm_AfterStartup, ext_ConnectMode.ext_cm_Startup
 
               ' Try to retrieve the command, just in case it was already created
               Try
                  myCommand = applicationObject.Commands.Item(addInInstance.ProgID & "." & "MyCommand")
               Catch
               End Try
 
               ' Add the command if it does not exists
               If myCommand Is Nothing Then
 
                  myCommand = applicationObject.Commands.AddNamedCommand(addInInstance, _
                     "MyCommand", "MyCommand", "Executes the command for MyAddin", True, 59, Nothing, _
                     vsCommandStatus.vsCommandStatusSupported Or vsCommandStatus.vsCommandStatusEnabled)

               End If
 
               ' Retrieve some built-in command bars
               standardCommandBar = applicationObject.CommandBars.Item("Standard")
               menuCommandBar = applicationObject.CommandBars.Item("MenuBar")
               toolsCommandBar = applicationObject.CommandBars.Item("Tools")
               codeCommandBar = applicationObject.CommandBars.Item("Code Window")
 
               ' Add a button to the built-in "Standard" toolbar
               myStandardCommandBarControl = myCommand.AddControl(standardCommandBar, _
                  standardCommandBar.Controls.Count + 1)

               myStandardCommandBarControl.Caption = MY_COMMAND_NAME
 
               ' Change the button style, which must be done casting the control to a button
               myCommandBarButton = DirectCast(myStandardCommandBarControl, CommandBarButton)
               myCommandBarButton.Style = MsoButtonStyle.msoButtonIcon
 
               ' Add a button to the built-in "Tools" menu
               myToolsCommandBarControl = myCommand.AddControl(toolsCommandBar, toolsCommandBar.Controls.Count + 1)
               myToolsCommandBarControl.Caption = MY_COMMAND_NAME
 
               ' Add a button to the built-in "Code Window" context menu
               myCodeWindowCommandBarControl = myCommand.AddControl(codeCommandBar, codeCommandBar.Controls.Count + 1)
               myCodeWindowCommandBarControl.Caption = MY_COMMAND_NAME
 
               ' Add a new toolbar with a button on it
               myTemporaryToolbar = applicationObject.CommandBars.Add("MyTemporaryToolbar", _
                  MsoBarPosition.msoBarTop, System.Type.Missing, True)
 
               ' Change the button style, which must be done casting the control to a button
               myCommandBarButton = DirectCast(myCommand.AddControl(myTemporaryToolbar), CommandBarButton)
               myCommandBarButton.Style = MsoButtonStyle.msoButtonIcon
 
               ' Make visible the toolbar
               myTemporaryToolbar.Visible = True
 
               ' Calculate the position of a new command bar popup by the "Tools" menu
               toolsCommandBarControl = DirectCast(toolsCommandBar.Parent, CommandBarControl)
               position = toolsCommandBarControl.Index + 1
 
               ' Add a new command bar popup with a button on it
               myTemporaryCommandBarPopup = DirectCast(menuCommandBar.Controls.Add( _
                  MsoControlType.msoControlPopup, System.Type.Missing, System.Type.Missing, _
                  position, True), CommandBarPopup)

               myTemporaryCommandBarPopup.CommandBar.Name = "MyTemporaryCommandBarPopup"
               myTemporaryCommandBarPopup.Caption = "My menu"
               myCommand.AddControl(myTemporaryCommandBarPopup.CommandBar)
               myTemporaryCommandBarPopup.Visible = True
 
         End Select
 
      Catch e As System.Exception
         System.Windows.Forms.MessageBox.Show(e.ToString)
      End Try
 
   End Sub
 
   Public Sub OnDisconnection(ByVal RemoveMode As Extensibility.ext_DisconnectMode, _
      ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnDisconnection
 
      Try
 
         If Not (myStandardCommandBarControl Is Nothing) Then
            myStandardCommandBarControl.Delete()
         End If
 
         If Not (myCodeWindowCommandBarControl Is Nothing) Then
            myCodeWindowCommandBarControl.Delete()
         End If
 
         If Not (myToolsCommandBarControl Is Nothing) Then
            myToolsCommandBarControl.Delete()
         End If
 
         If Not (myTemporaryToolbar Is Nothing) Then
            myTemporaryToolbar.Delete()
         End If
 
         If Not (myTemporaryCommandBarPopup Is Nothing) Then
            myTemporaryCommandBarPopup.Delete()
         End If
 
      Catch e As System.Exception
         System.Windows.Forms.MessageBox.Show(e.ToString)
      End Try
 
   End Sub
 
   Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnBeginShutdown
   End Sub
 
   Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnAddInsUpdate
   End Sub
 
   Public Sub OnStartupComplete(ByRef custom As System.Array) Implements _
      Extensibility.IDTExtensibility2.OnStartupComplete
   End Sub
 
   Public Sub Exec(ByVal cmdName As String, ByVal executeOption As vsCommandExecOption, _
      ByRef varIn As Object, ByRef varOut As Object, ByRef handled As Boolean) Implements IDTCommandTarget.Exec
 
      handled = False
 
      If (executeOption = vsCommandExecOption.vsCommandExecOptionDoDefault) Then
 
         If cmdName = addInInstance.ProgID & "." & MY_COMMAND_NAME Then

            handled = True
            System.Windows.Forms.MessageBox.Show("Command executed.")

         End If
 
      End If
 
   End Sub
 
   Public Sub QueryStatus(ByVal cmdName As String, ByVal neededText As vsCommandStatusTextWanted, _
      ByRef statusOption As vsCommandStatus, ByRef commandText As Object) Implements IDTCommandTarget.QueryStatus
 
      If neededText = EnvDTE.vsCommandStatusTextWanted.vsCommandStatusTextWantedNone Then
 
         If cmdName = addInInstance.ProgID & "." & MY_COMMAND_NAME Then
            statusOption = CType(vsCommandStatus.vsCommandStatusEnabled + _
               vsCommandStatus.vsCommandStatusSupported, vsCommandStatus)
         Else
            statusOption = vsCommandStatus.vsCommandStatusUnsupported
         End If
 
      End If
 
   End Sub
 
End Class

 
References:

HOWTO: Guessing the name of a command bar to add a custom menu entry in Visual Studio .NET add-ins.


HOWTO: Add a popup command bar to the context menu of a code window of Visual Studio .NET.
 

HOWTO: Getting the "View" command bar of Visual Studio .NET from an add-in.


HOWTO: Removing commands and UI elements during Visual Studio .NET add-in uninstallation.

 
BUG: Add-in reloaded after unloaded in Visual Studio .NET.

 
 
 
Properties

Article ID: 555326 - Last Review: 14 Feb 2017 - Revision: 1

Microsoft Visual Studio .NET 2002 Enterprise Developer, Microsoft Visual Studio .NET 2002 Professional Edition, Microsoft Visual Studio .NET 2003 Enterprise Architect, Microsoft Visual Studio .NET 2003 Enterprise Developer, Microsoft Visual Studio .NET 2003 Professional Edition

Feedback