Outlook Developer Home
Outlook Programmer's Library
Outlook Technologies
Outlook Forms
Other Technologies



VSTO Sample: Saving a Custom Toolbar's Position

Many Outlook add-ins provide user interaction through a custom toolbar. This VB.NET sample for Visual Studio 2005 Tools for Office demonstrates:

  • How to extend a class in Visual Studio 2005 with the Partial keyword
  • How to create a custom toolbar and button in Outlook's Explorer window
  • How to use user-scoped settings in Visual Studio 2005 to save the toolbar's position information in a user.config XML file and restore the toolbar to that position with Outlook starts
  • Some other best practices for working with Outlook COM add-in toolbars

This sample requires Visual Studio 2005 Tools for Office. It will not work with simply Visual Studio 2005 Beta 2 or any earlier version of Visual Studio.

Setup | Project Settings | ThisApplication.vb | CommandBarWithPositionInfo class | Toolbar Initialization | Toolbar Shutdown | Known Issues | | More Information


Solution Explorer - click for larger imageDownload the solution (CommandBarPositionSaver.zip, 14 Jun 2005, 76kb), and extract the files. Open the CommandBarPositionSaver.sln solution in Visual Studio 2005 Beta 2 or later. You should see the project items shown at left (click for larger image).
Back to Top

Project Settings

Project Settings - click for larger imageIf you open My Project and look at the Settings tab at the right (click for larger image), you will see that the project contains seven user-scoped settings related to toolbar position and size. In particular, note that the Position setting uses the Microsoft.Office.Core.MsoBarPosition enumeration. This was selected by clicking the Type dropdown list and then browsing to the desired type.

As you will see below, the settings are used to persist the toolbar location between Outlook sessions.

Back to Top


Each VSTO Outlook add-in contains a basic ThisApplication class with Startup and Shutdown events. In this add-in, these event handlers simply initialize and perform shutdown tasks for a custom toolbar:

Back to Top

CommandBarWithPositionInfo class

The CommandBarWithPositionInfo class consists of two public properties and one public method (plus private methods to handle instantiating and disposing of a class instance):
  • The CommandBar property reads or sets an Office.CommandBar object.
  • The read-only PositionName property returns a string corresponding to the CommandBar.Position property (which uses the Microsoft.Office.Core.MsoBarPosition enumeration).
  • The SaveSettings method saves the position information for the toolbar represented by the CommandBar property to the settings defined for the application:

The My.Settings.Save method saves the settings to a user.config file unique to the add-in and stored in the user's %AppData% hierarchy. Note that you can refer to each setting directly by name, rather than being forced to iterate a collection.

Back to Top

Toolbar Initialization

The InitToolbar and UninitToolbar procedures called from the ThisApplication_Startup and ThisApplication_Shutdown event handlers are found in ThisApplication.InitializeMenu.vb, a class module that extends the ThisApplication class by prefacing the class declaration with the Partial keyword for which VS 2005 adds support. This class contains two private object variables declared at the module level so that they do not go out of scope and get released by the .NET garbage collector:

CommandBarWithPositionInfo is the separate class discussed above that facilitates the reading and saving of toolbar position settings to the project settings.

The InitToolbar procedure creates a new toolbar and button in a manner that should look familiar to VB6 developers -- check for the existence of the toolbar first, create the toolbar if necessary (setting its Temporary parameter to True), then add the button.

The last argument in the statement to create the toolbar sets the Temporary parameter to True:

_showSettingsMessage = _toolbar.Controls.Add _
    (Office.MsoControlType.msoControlButton, _
    Type.Missing, Type.Missing, Type.Missing, True)

By recreating the toolbar anew for each Outlook session, you handle the scenario where the user uninstalls the add-in between sessions. This, of course, is the reason for providing a means to persist the toolbar position settings between sessions: Since the toolbar is temporary, its position is not stored in the Outcmd.dat file with that of other toolbars.

Because the code has to use the toolbar name to determine if the toolbar already exists, when we create the toolbar, we protect it against the user changing the name or adding/removing buttons with this statement:

_toolbar.Protection = _

One thing that's different with this code compared with the analogous technique in VB6 is how the event handler for the button's Click event is set up. It is not necessary to declare a CommandBarButton object variable WithEvents. Instead, this code statement assigns the Click event for the _showSettingsMessage button to an event handler procedure:

    AddHandler _showSettingsMessage.Click, _
                AddressOf _showSettingsMessage_Click

The name of the event handler is _showSettingsMessage_Click, just as it would be for an event handler for an object declared WithEvents, but it is not necessary for the names to match. The procedure could just as well have been named ButtonClickHandlerDemo, as long as the AddressOf operator points to a procedure by that name. (TIP: This technique can be extended to wire more than one event to the same handler, for example, the Click event for multiple option buttons on a Windows form.)

Note that the button's object variable (_showSettingsMessage) is declared at the module level, not at the procedure level, to ensure that the variable stays active for the life of the add-in. The _showSettingsMessage_Click procedure shows a message box with information about the current toolbar position.

Also note how easy it is to use the My.Settings.<property> values to set the position and size attributes for the toolbar, without any explicit code to read from the user.config file where they were stored by the SaveSettings procedure

Back to Top

Toolbar Shutdown

When Outlook shuts down or the add-in is removed by the user, the ThisApplication.Shutdown event fires, and the add-in stores the user's toolbar position preference by calling this statement from the UnintToolbar procedure:

As you saw above, _toolbarWithPositionInfo is a module-level object, an instance of the CommandBarWithPositionInfo class, which contains the SaveSettings procedure.  What is interesting is that, at the point where ThisApplication.Shutdown fires, Outlook may no longer have any active Explorer windows, and therefore, an attempt to obtain the toolbar settings from the ActiveExplorer.CommandBars collection may fail. However, the _toolbarWithPositionInfo object is still in scope and, therefore, its CommandBar property is still available to provide the position and size information.

Back to Top

Known Issues

If Outlook is started by an external application that does not display an Outlook folder window (aka Explorer), the ThisApplication_Startup event handler will not run and, therefore, the toolbar will not be displayed.

This sample only adds the button to the first Explorer window shown when Outlook starts. To handle the case where you have two Explorer windows open and want the both to show the same button and have it fire independently would require Explorers wrapper class. See CommandBar & ExplorerWrapper c# example for an example in C# (but not built with VSTO). In the multi-window scenario, which window's toolbar position would you want to save -- the main Outlook window, i.e. the one first opened? Or would you want the toolbar to automatically be in the same position for each window?

Back to Top

More Information

2002-7 TurtleFlock, LLC
All right reserved.
About OutlookCode.com

Send comments to webmaster@outlookcode.com

Designed and Implemented by TerraLink USA 

FrontPage Integration
by RobsonDesignWorks

get Sue's code | forums | share your own code | registration