Programming the Outlook 2010 Solutions Module

Summary: In Microsoft Office Outlook 2007, developers can create folders programmatically and navigate to them on the Navigation Pane, as long as those folders contain built-in Outlook items such as mail, calendar (including meeting requests and appointments), contact, task, journal, or note items. In Microsoft Outlook 2010, developers can further navigate to folders that contain custom item types by using the Solutions module. This article introduces the Solutions module, provides examples of the problems that the Solutions module solves, and then walks through a sample add-in to illustrate how to implement the Solutions module. (10 printed pages)

Applies to: Office 2010 | Outlook 2010

In this article
Overview
Outlook Navigation Modules
Problem Statement
Programming the Solutions Module
Sample Add-in
Additional Notes
Conclusion
Additional Resources

Published:  November 2009 | Updated:  December 2010

Provided by:  Randy Byrne, Microsoft Corporation

Click to grab code  Outlook 2010 Sample: Programming the Solutions Module

Contents

  • Overview

  • Outlook Navigation Modules

  • Problem Statement

  • Programming the Solutions Module

  • Sample Add-in

  • Additional Notes

  • Conclusion

  • Additional Resources

Overview

Over the years, developers have requested the ability to add custom modules to the Navigation Pane in Outlook. Microsoft Outlook 2010 provides that capability through the Solutions module object model. The Solutions module is a navigation module that you can add to the Navigation Pane programmatically. In fact, it can be created only through code; you cannot create the module through the user interface. The Solutions module gives users a powerful way to search folder hierarchies or stores that contain customized item types. For example, a customer relationship management (CRM) application could expose custom item types such as business contacts, accounts, and opportunities in the Solutions module. Additionally, Outlook 2010 gives the add-in developer a way to set a custom folder icon for each folder that contains custom item types. Figure 1 shows an example of the Solutions module Solution Demo.

Figure 1. Example Solutions module in Outlook 2010

Example Solutions module in Outlook 2010

Outlook Navigation Modules

Outlook 2007 supports a rich model that you can use to build solutions that have their own custom folders. Those folders can contain built-in Outlook item types such as mail, calendar items, contacts, and tasks. The existing navigation modules work very well to navigate to these folders. Some examples of navigation modules that match built-in Outlook item types include the following:

  • The Contacts and Folder List navigation modules can display folders that contain items of the contact item type. For example:

    • A folder for the Human Resources group might contain a list of interview candidates that is accessible by recruiters.

    • A folder for the Sales group might contain a list of leads that is accessible by sales professionals.

  • The Calendar and Folder List navigation modules can display folders that match calendar item types. For example:

    • A folder for the Human Resources group might contain appointments in their interview schedules.

    • A folder for the Sales group might contain account-planning milestones.

  • The Task and Folder List navigation modules can display folders that contain items of the task type. For example, a folder for the Human Resources group might contain the interview tasks shared by a group of recruiters.

  • The Shortcuts navigation module can display folders of different types that you want to group together. For example, a shortcuts module for the Human Resources group might display folders of the following types:

    • Contacts for interview candidates.

    • Calendar items for the interview schedule.

    • Tasks for the recruiting process.

Figure 2 shows a Venn diagram that illustrates the relationship between different navigation modules.

Figure 2. Navigation modules in Outlook 2007

Navigation modules in Outlook 2007

Problem Statement

A problem occurs when developers want to introduce folders for new constructs that do not match any built-in Outlook item types, and yet must appear in Outlook to support the end user's scenarios and activities. Developers cannot provide users an intuitive way to navigate to these folders. For example, the folders might include the following:

  • A list of opportunities for the Sales group.

  • A list of requisition orders for the Human Resources group.

  • A list of marketing campaigns for the Marketing group.

The end user does not expect to see these lists of data in existing navigation modules (except the Folder List). With the Solutions module in Outlook 2010, developers enable the following capabilities that solve the problem:

  • Use the new Solutions module to display folders that do not belong in the Mail, Calendar, Contacts, Tasks, Notes, and Journal navigation modules.

  • Specify the root folder for items of this new custom type and the name of the Solutions module under which the root folder should be organized. Developers can use the AddSolution method of the SolutionsModule object to specify a root folder that corresponds to a solution to be added to the Solutions module. If the developer sets the Scope parameter of the AddSolution method to OlSolutionScope.olHideInDefaultModules, any folders specified as this new type appear only under the new Solutions module and the Folder List. If the developer sets the Scope parameter to OlSolutionScope.olShowInDefaultModules, then folders appear in their default modules, the Folder List, and the Solutions module.

Figure 3 shows an updated Venn diagram that includes the Solutions module in Outlook 2010 (if Scope is equal to olHideInDefaultModules).

Figure 3. Solutions and navigation modules in Outlook 2010

Solutions and navigation modules in Outlook 2010

Programming the Solutions Module

To display the Solutions module in the Navigation Pane, your add-in must do the following:

  1. Create an instance of the SolutionsModule object.

  2. Call the AddSolution method of the SolutionsModule object and pass a Folder object that represents the solution root folder. Subsequently, all folders under the solution root folder are added to the Solutions module. The OlSolutionScope enumeration specifies whether the solution root folder and its subfolders appear in their default modules in the Navigation Pane.

  3. If necessary, set the Position property of the SolutionsModule object to ensure that the Solutions module button is displayed as a large button in the Navigation Pane.

Sample Add-in

The sample add-in that accompanies this article is named SolutionsModuleAddinCS. It uses Microsoft Visual C# and requires Microsoft Visual Studio 2008 Service Pack 1 and Outlook 2010.

Installation Instructions

Follow these steps to install the sample add-in:

  1. Download the Outlook_2010_Programming_the_Solutions_Module.zip file from the MSDN Samples Gallery.

  2. Extract the .zip file into the folder of your choice. In Windows Vista, the default path for Visual Studio 2008 projects is C:\Users\user\Documents\Visual Studio 2008\Projects.

Follow these steps to run SolutionsModuleAddinCS:

  1. Close Outlook.

  2. In the folder where you extracted the SolutionsModuleAddinCS.zip file, open the SolutionsModuleAddinCS solution.

  3. On the Build menu, click Build SolutionsModuleAddinCS.

  4. Start Outlook to start the add-in in run mode, or press F5 to start the add-in in debug mode. If Outlook does not start in debug mode, complete the following procedure.

To start Outlook in debug mode:

  1. In Solution Explorer, select SolutionsModuleAddinCS.

  2. On the Project menu, click SolutionsModuleAddinCS Properties, and then click the Debug tab.

  3. Under Start Action, select the Start External Program option, and then click Browse.

  4. In the [Drive:]\Program Files\Microsoft Office\Office14 folder, click Outlook.exe.

  5. Press F5 to start the add-in in debug mode.

Code Walkthrough

The SolutionsModuleAddinCS code is concise and limited in scope. Its sole purpose is to turn on the Solutions module programmatically and, as a bonus feature, to customize the folder icons for the Solutions module. There is one method in the sample code, EnsureSolutionsModule, that is called from the Startup method of the ThisAddin class. The Startup method for the Solutions module add-in typically runs when Outlook starts, and guarantees visibility of your solution during a first run condition and every time that Outlook starts after that.

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    // Call EnsureSolutionsModule to ensure that the
    // Solutions module and the custom folder icons
    // appear in the Outlook Navigation Pane.
    EnsureSolutionsModule(); 
}

Before you add a solution to the Solutions module, carefully design the folder hierarchy that you want to appear in the Solutions module. The root folder of your solution is called the solution root folder, and should be named so that it clearly identifies your solution to the end user. If only one solution is installed in the Solutions module, the name of the solution root folder becomes the label of the Solutions module button. If more than one solution is installed, the label of the Solutions module button reverts to Solutions and a tooltip appears that contains the name of each solution root folder in the Solutions module.

In the EnsureSolutionsModule method, the solution root folder is named Solution Demo. If that folder does not exist, it is created in the default store that is represented by the rootStoreFolder instance variable. Additional solution folders named Solution Calendar and so on are created as subfolders of Solution Demo. Note that all subfolders of the solution root folder must be children of that solution root folder. You cannot add a solution root folder that contains folders in different stores or that are children of another solution root folder. A solution root folder can exist in a personal folders file (.pst) or in a custom store provider. If that is the case, obtain a Folder object that represents the solution root folder in your .pst or custom store. The following is the relevant code from the EnsureSolutionsModule method.

bool firstRun = false ;
Outlook.Folder rootStoreFolder =
    Application.Session.DefaultStore.GetRootFolder()
    as Outlook.Folder;
// If the solution root folder does not exist, create it.
// Note that the solution root 
// could also be in a PST or custom store.
try
{
    solutionRoot =
        rootStoreFolder.Folders["Solution Demo"]
        as Outlook.Folder;
}
catch
{
    firstRun = true;
}

If the Solution Demo folder does not exist, the firstRun variable is set to true; otherwise, it is false. In either case, the code sets the instance variables, such as solutionCalendar and solutionContacts, to point to each subfolder in the solution root folder. These instance variables are used to set custom folder icons for each solution subfolder and the solution root folder.

You can use the SetCustomIcon method of the Folder object to set the custom folder icon for a folder. This custom folder icon does not persist and must be set each time that the add-in loads. Furthermore, you must set the icon with a 16x16 icon resource as an IPictureDisp object. Because an IPictureDisp object cannot be passed across process boundaries, you must call SetCustomIcon from an add-in that is running in-process to Outlook. SetCustomIcon raises an error if you call it from an application that runs out-of-proc to Outlook. The PictureDispConverter class that is defined in the add-in project converts an icon resource to an IPictureDisp object. Because this class does not relate directly to the Solutions module scenario, it is not discussed in this walkthrough.

After you set all the folder icons, you must obtain an instance variable named solutionsModule by using the following code.

// Obtain a reference to the SolutionsModule object.
Outlook.Explorer explorer = Application.ActiveExplorer();
Outlook.SolutionsModule solutionsModule =
    explorer.NavigationPane.Modules.GetNavigationModule(
    Outlook.OlNavigationModuleType.olModuleSolutions)
    as Outlook.SolutionsModule;

The GetNavigationModule method of the Modules object returns a SolutionsModule object when you specify olModuleSolutions as the type of module. Next, call the AddSolution method, passing a Folder object that represents your solution root folder and an OlSolutionScope value that determines whether the solution root folder and its subfolders appear in default Navigation Pane modules such as Mail, Calendar, Contacts, or Tasks. If OlSolutionScope is equal to olHideInDefaultModules, the solution root folder and its subfolders only appear in the solution module and the Folder List module. If OlSolutionScope is equal to olShowInDefaultModules, the solution root folder and its subfolders appear in the solution module, the Folder List module, and default modules, depending on the folder type. For example, folders of a calendar item type in the solution module also appear in the Calendar module if OlSolutionScope is equal to olShowInDefaultModules.

Certain folders are invalid as solution root folders and raise an error when you call the AddSolution method. Note that a folder that is the root folder of a PST store or a custom store is a valid solution root folder. The following are invalid solution root folders:

  • Default or special folders. Default folders are represented by the OlDefaultFolders enumeration and special folders are represented by the OlSpecialFolders enumeration.

  • A folder that is already a solution root folder for a different solution.

  • A folder that is a subfolder of an existing solution root folder.

  • A folder that is a parent folder of an existing solution root folder.

The following code example calls the AddSolution method to specify the solution root folder that appears in the Solutions module and the Folder List module only.

// Add the solution and hide folders in default modules.
solutionsModule.AddSolution(solutionRoot,
    Outlook.OlSolutionScope.olHideInDefaultModules);

Finally, you can control the position and size of the Solutions module button in the Navigation Pane. Use the Visible, Position, and the DisplayedModuleCount properties of the SolutionsModule object to determine the visibility, position, and the module button size of the Solutions module. If the DisplayedModuleCount is less than the Position property of the SolutionsModule object, then the module button is a small one instead of a large one.

// The following code sets the position and visibility
// of the Solutions module.
if (solutionsModule.Visible == false)
{
    // Set Visibile to true.
    solutionsModule.Visible = true;
}
if (solutionsModule.Position != 5)
{
    // Move SolutionsModule to Position = 5.
    solutionsModule.Position = 5;
}
// Create an instance variable for the Navigation Pane.
Outlook.NavigationPane navPane = explorer.NavigationPane;
if (navPane.DisplayedModuleCount != 5)
{
    // Ensure that the Solutions module button is large.
    navPane.DisplayedModuleCount = 5;
}

The following is the complete code of the EnsureSolutionsModule method for those who want to inspect the method in its entirety.

private void EnsureSolutionsModule()
{
    try
    {
        // Declarations.
        Outlook.Folder solutionRoot;
        Outlook.Folder solutionCalendar;
        Outlook.Folder solutionContacts;
        Outlook.Folder solutionTasks;
        bool firstRun = false ;
        Outlook.Folder rootStoreFolder =
            Application.Session.DefaultStore.GetRootFolder()
            as Outlook.Folder;
        // If the solution root folder does not exist, create it.
        // Note that the solution root 
        // could also be in a PST or custom store.
        try
        {
            solutionRoot =
                rootStoreFolder.Folders["Solution Demo"]
                as Outlook.Folder;
        }
        catch
        {
            firstRun = true;
        }

        if (firstRun == true)
        {
            solutionRoot =
                rootStoreFolder.Folders.Add("Solution Demo",
                Outlook.OlDefaultFolders.olFolderInbox) 
                as Outlook.Folder;
            solutionCalendar = solutionRoot.Folders.Add(
                "Solution Calendar", 
                Outlook.OlDefaultFolders.olFolderCalendar)
                as Outlook.Folder;
            solutionContacts = solutionRoot.Folders.Add(
                "Solution Contacts", 
                Outlook.OlDefaultFolders.olFolderContacts)
                as Outlook.Folder;
            solutionTasks = solutionRoot.Folders.Add(
                "Solution Tasks", 
                Outlook.OlDefaultFolders.olFolderTasks)
                as Outlook.Folder;
        }
        else
        {
            solutionRoot =
                rootStoreFolder.Folders["Solution Demo"]
                as Outlook.Folder;
            solutionCalendar = solutionRoot.Folders[
                "Solution Calendar"]
                as Outlook.Folder;
            solutionContacts = solutionRoot.Folders[
                "Solution Contacts"]
                as Outlook.Folder;
            solutionTasks = solutionRoot.Folders[
                "Solution Tasks"]
                as Outlook.Folder;
        } 
        // Get the icons for the solution.
        stdole.StdPicture rootPict = 
            PictureDispConverter.ToIPictureDisp(
            Properties.Resources.BRIDGE)
            as stdole.StdPicture;
        stdole.StdPicture calPict = 
            PictureDispConverter.ToIPictureDisp(
            Properties.Resources.umbrella)
            as stdole.StdPicture;
        stdole.StdPicture contactsPict = 
            PictureDispConverter.ToIPictureDisp(
            Properties.Resources.group)
            as stdole.StdPicture;
        stdole.StdPicture tasksPict = 
            PictureDispConverter.ToIPictureDisp(
            Properties.Resources.SUN)
            as stdole.StdPicture;
        // Set the icons for the solution folders.
        solutionRoot.SetCustomIcon(rootPict);
        solutionCalendar.SetCustomIcon(calPict);
        solutionContacts.SetCustomIcon(contactsPict);
        solutionTasks.SetCustomIcon(tasksPict);
        // Obtain a reference to the Solutions module.
        Outlook.Explorer explorer = Application.ActiveExplorer();
        solutionsModule =
            explorer.NavigationPane.Modules.GetNavigationModule(
            Outlook.OlNavigationModuleType.olModuleSolutions)
            as Outlook.SolutionsModule;
        // Add the solution and hide folders in default modules.
        solutionsModule.AddSolution(solutionRoot, 
            Outlook.OlSolutionScope.olHideInDefaultModules);
        // The following code sets the position and visibility
        // of the Solutions module.
        if (solutionsModule.Visible == false)
        {
            // Set Visibile to true
            solutionsModule.Visible = true;
        }
        if (solutionsModule.Position != 5)
        {
            // Move SolutionsModule to Position = 5
            solutionsModule.Position = 5;
        }
        // Create an instance variable for the Navigation Pane.
        Outlook.NavigationPane navPane = explorer.NavigationPane;
        if (navPane.DisplayedModuleCount != 5)
        {
            // Ensure that the Solutions module button is large.
            navPane.DisplayedModuleCount = 5;
        }
    }
    catch (Exception ex)
    {
        Debug.Write(ex.Message);
    }
}

Additional Notes

When an end-user navigates to the Solutions module and makes a solution folder in the Solutions module the current folder, Outlook returns to that folder setting in the Solutions module when the end-user navigates away from, and then back to, the Solutions module. However, the current folder setting in the Solutions module does not persist between Outlook sessions.

Conclusion

The Solutions module gives developers an important piece of the user interface in Outlook 2010. Although Outlook supports only one Solutions module for all solutions, as a developer, you can use the Solutions module to integrate your solutions seamlessly with the Outlook Navigation Pane in ways that were not possible in previous versions of Outlook.

Additional Resources

For more information, see the following resources: