Microsoft KB Archive/201095

From BetaArchive Wiki

Article ID: 201095

Article Last Modified on 11/19/2005



APPLIES TO

  • Microsoft Outlook 2000 Standard Edition
  • Microsoft Outlook 2002 Standard Edition



This article was previously published under Q201095


SUMMARY

Although Microsoft Outlook uses the same CommandBars that other Microsoft Office applications use, CommandBars are implemented in a different manner in Outlook. This article describes the differences in CommandBar implementation, so that developers can better understand how to work with CommandBars when they design an Outlook solution.


MORE INFORMATION

In Office, each Office application's menus and toolbars are represented by a CommandBars object model. CommandBars are a shared Office component, and the object model is provided in the Microsoft Office 10.0 Object Library. The CommandBars object model is not contained in the Outlook object model; instead, the Outlook object "tunnels" into the Microsoft Office 10.0 Object Library for this functionality.

Outlook CommandBar Architecture

Other Office applications support one set of CommandBars, but Outlook supports two: one set at the main application window, and a second set in each individual item.

From a developer's point of view, the main window in Outlook (the application window) is referred to as an "explorer."

IMPORTANT: These windows can also be considered folder-level windows because you can right-click any folder, and then click Open in New Window to open different windows to work with different folders.

In addition to these explorer windows, each Outlook item has a form window that is referred to as an "inspector." These inspector windows also have a set of CommandBars because items have menus and toolbars.

Use the different objects as follows:

  • Use the Explorer objects (ActiveExplorer/GetExplorer) to refer to the main application window in Outlook.
  • Use the Inspector objects (ActiveInspector/GetInspector) to refer to an Outlook item's window.
                 |  To refer to the                  |  To refer to a folder
   Window type   |  "active" window                  |  or item's window
   ---------------------------------------------------------------------------------
   Application   |  Use the ActiveExplorer method.   |  Use the GetExplorer method.
                 |                                   |
   Item or Form  |  Use the ActiveInspector method.  |  Use the GetInspector method.
                

Considerations When You Use Microsoft Word as the E-Mail Editor

When you are designing an Outlook CommandBar solution for mail items, it is important that you understand that different CommandBars are used when Microsoft Word is set as the e-mail editor. Some key points that you must consider when you use Word as the e-mail editor are:

  • CommandBars are part of Word, not Outlook.
  • Different CommandBars are available based on the message editor and format.
  • Custom buttons may disappear when you change message editor or format.
  • The special Envelope CommandBar is not designed to be customized.
  • There is no Inspector object for the HTML and Plain Text formats with Office 2000 if Word is set as the e-mail editor.

The available CommandBars may change based on the different editors (Outlook versus Word) and different message formats (Rich Text Format, HTML, and Plain Text); therefore, it is important that you test your solution thoroughly in each configuration. Because different CommandBars are available in different configurations, it is common for a button that you add in one configuration to no longer be displayed after you change to another configuration. With Word set as the e-mail editor, the Word application provides the item-level (inspector) CommandBars. Although some of these Word CommandBars are accessible through the Inspector object if you use Microsoft Office 2002, this is not the case in Microsoft Office 2000. In Office 2000, the HTML and Plain Text messages do not have Inspector objects if you use Word as the e-mail editor; therefore, you need to access the CommandBars by using the Word object model. The storage location for CommandBar customizations also changes based on which application provides the CommandBars. Customizations that you make to the standard Outlook CommandBars are stored in the Outcmd.dat file. Customizations that you make to the Word CommandBars are stored in the Word Normal.dot global template.

Word also provides two different sets of CommandBar technologies based on the format of the e-mail message. In Office 2002, all of the message formats use the specialized Envelope CommandBar by default, but in Office 2000, only HTML and Plain Text messages use the Envelope CommandBar. The Envelope CommandBar contains features that are specific to e-mail, such as the Send button and message fields (To, Cc, and Subject). The Envelope CommandBar is not displayed in the Word Toolbars list and is not designed to be customized. Therefore, you must make any modifications to other CommandBars. Office 2000 handles Rich Text Format messages differently and uses the Outlook Send Mail and Outlook Read Mail CommandBars for composing and reading messages. Although Office 2002 message formats do not use the Outlook Send Mail and Outlook Read Mail CommandBars by default, you can design a custom Outlook form that uses these CommandBars. To configure the form so that it uses Word as the e-mail editor, in form design mode, click the Properties tab of the form, and then click to select Always use Microsoft Word as the e-mail editor.

A History of Outlook Support for Customizable Menus and Toolbars

CommandBars were originally designed for document-centric applications, such as Word and Microsoft Excel, which support a single set of application-level CommandBars. The other applications fully support all of the features of the CommandBars design, and in Microsoft Office 97 and later, the other applications fully support many aspects of customizing CommandBars. However, Outlook has continued to support CommandBars is various ways:

  • In Microsoft Outlook 97, you cannot customize toolbars and menus by using the Outlook user interface. Outlook 97 is not designed to store changes to CommandBars. Although the CommandBars object model is exposed in the Outlook object model, you cannot use the CommandBars object model to modify the menus or toolbars because they are in a "read-only" state. However, you can use the Execute method to programmatically run a built-in Outlook command. The only way to create additional toolbar buttons or menu commands in Outlook 97 is to create a Microsoft Exchange Client Extension in C or C++.
  • In Microsoft Outlook 98, Microsoft recommends that you do not programmatically make changes to the CommandBars object model. Toolbars and menus are customizable in the Outlook user interface. Customizations are stored in a file called Outcmd.dat. However, although the CommandBars object model is exposed in the Outlook object model, and you can programmatically add new toolbar buttons and menu commands, this feature was not designed or tested to actually work. As a result, you may experience issues if you use the CommandBars object model in Outlook 98. Outlook 98 does not support Microsoft Visual Basic for Applications (VBA), or application-level code. Therefore, if you programmatically add a custom command to an application-level window, or explorer, there is no way to attach custom code to the button. If you programmatically add a custom command to an item-level window, or inspector, you can have the button run custom Microsoft Visual Basic Scripting Edition (VBScript) script in the form, but issues will occur that cause the button to be displayed on other types of items, and there may be differences between opening new items and existing items.
  • Outlook 2000 is the first version of Outlook that is designed to support programmatically customizable toolbars and menus. This coincides with the addition of support for VBA and Component Object Model (COM) add-ins.

CommandBars and the Outlook Object Model

In the object models of other Office applications, the CommandBars collection is located off the Application object because those applications support only one set of application-level CommandBars. However, the Outlook object model is designed to support the two sets of CommandBars that Outlook supports (Inspector and Explorer).

In the Outlook object model, the CommandBars collection is located off Explorer and Inspector objects, not the Outlook Application object. Many code examples are available that illustrate how to programmatically make changes to CommandBars; however, most of these examples are designed for other Office applications. To use these examples in Outlook, you must modify the code appropriately to reflect the difference in the Outlook object model.

Custom Form Solutions

In a custom form solution that uses VBScript, you typically access the form-level CommandBars by using code that is similar to:

Set objCBs = Item.GetInspector.CommandBars
                

A VBScript Sample to Run an Outlook Command

You can use the following sample code with a CommandButton control on a contact form to easily create a new letter for a Contact:

Sub CommandButton1_Click()
   Set MyCB = Item.GetInspector.CommandBars.Item("Menu Bar")
   Set MyMenu = MyCB.Controls("Actions")
   Set MyMenuItem = MyMenu.Controls("New Letter to Contact")
   MyMenuItem.Execute()
End Sub
                

A VBScript Sample That Uses the "FindControl" Method

If you know the internal value that Outlook has assigned for each command, you can use the FindControl method to reference any Outlook commands (or controls, in relation to the CommandBars object model). If you use the internal ID, you can use more concise syntax when running CommandBar commands, and you can access commands that may not be on the menu or toolbar that is displayed.

For example, consider a custom Outlook form that uses a custom command button to print the form. Assuming that the command button is named cmdPrint, either of the following two VBScript code examples displays the File Print dialog box:

Sub cmdPrint_Click()
   Item.GetInspector.CommandBars.FindControl(,4).Execute
End Sub

Sub cmdPrint_Click()
   Item.GetInspector.CommandBars.Item("Menu Bar").Controls("File") _
      .Controls("Print...").Execute
End Sub
                

For an example of how to generate a list of Outlook CommandBar control IDs, see the Excel example in the "Using an Excel Utility to Generate a List of Outlook CommandBar IDs" section of this article.

Application-Level Solutions

In an application-level solution, such as Outlook VBA or a COM add-in, the typical method to access the application-level CommandBars is to use code that is similar to:

Set objCBs = Application.ActiveExplorer.CommandBars
                

Visual Basic for Applications

Outlook VBA is designed to be a personal development tool; these types of solutions are not designed to be deployed. Therefore, typically, you would not programmatically customize CommandBars from Outlook VBA. Instead, manually create the custom CommandBar button:

  1. On the Tools menu, click Customize.
  2. Click the Commands tab, and then click Macros in the list of categories.
  3. Drag a macro to the menu or toolbar.
  4. To modify the appearance of the toolbar or menu command, in the Customize window, click Modify Selection, and then make any modifications to the custom toolbar or menu command.
  5. Click Close.

A VBA Sample to Add a CommandBar Control

To add a CommandBar control:

  1. Create a sample custom Outlook Post form, and then publish it to your Inbox. Name it TestForm.
  2. On the Tools menu, point to Macro, and then click Visual Basic Editor.
  3. Under Project - Project1, double-click Project1, double-click Microsoft Outlook Objects, and then double-click ThisOutlookSession.
  4. In the code window, enter the following code:

    Dim WithEvents myControl As CommandBarButton
    
    Private Sub Application_Startup()
    
       Dim oExp As Outlook.Explorer
       Dim oBar As Office.CommandBar
    
       Set oExp = Outlook.ActiveExplorer
       Set oBar = oExp.CommandBars.Item("Standard")
    
       ' See if button already exists based on Tag value
       Set myControl = oBar.FindControl(, , "OpenForm")
    
       ' If not found then create button
       If myControl Is Nothing Then
          Set myControl = oBar.Controls.Add(, , , 2, True)
          With myControl
             .Caption = "Open Form"
             .FaceId = 59
             .Style = msoButtonIconAndCaption
             .Tag = "OpenForm"
             .Visible = True
          End With
       End If
    
    End Sub
    
    Private Sub myControl_Click(ByVal Ctrl As _
          Office.CommandBarButton, CancelDefault As Boolean)
          
       Dim myFolder As MAPIFolder
    
       Set myFolder = Session.GetDefaultFolder(olFolderInbox)
       Set MyItem = myFolder.Items.Add("IPM.Post.TestForm")
       MyItem.Display
    
       Set MyItem = Nothing
       Set myFolder = Nothing
    
    End Sub
                        
  5. Close the Visual Basic Editor.
  6. Close Outlook. When you are prompted to save changes to the VBA project, click Yes.
  7. Start Outlook.

back to list of topics

A COM Add-In Sample to Add a CommandBar Control

The supported way to distribute application-level code to Outlook users is by creating a COM add-in. The following COM add-in code sample demonstrates how to add a new button to the first position on the Standard Outlook CommandBar (you can also set the OnAction property of the button to load the COM add-in if it is not already loaded):

Dim OL As Outlook.Application
Dim WithEvents objButton As Office.CommandBarButton

Private Sub AddinInstance_OnConnection(ByVal Application As Object, _
   ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
   ByVal AddInInst As Object, custom() As Variant)

   Dim objBar As Office.CommandBar
   Set OL = Application
   Set objBar = OL.ActiveExplorer.CommandBars.Item("Standard")
   Set objButton = objBar.Controls.Add(, , , 1, True)
   With objButton
      .FaceId = 59
      .Caption = "My Button"
      .Style = msoButtonIconAndCaption

      ' The OnAction property is optional but recommended. 
      ' It should be set to the ProgID of the add-in, such that if
      ' the add-in is not loaded when a user presses the button,
      ' Outlook loads the add-in automatically and then raises
      ' the Click event for the add-in to handle. 

      .OnAction = "!<" & AddInInst.ProgId & ">"
   End With

End Sub

Private Sub objButton_Click(ByVal Ctrl As Office.CommandBarButton, _
   CancelDefault As Boolean)

   MsgBox "Hello World"

End Sub
                

For additional information about available resources for creating COM Add-Ins for Outlook, click the article number below to view the article in the Microsoft Knowledge Base:

230225 OL2000: How to Create a COM Add-in for Outlook


Using a Microsoft Excel Utility to Generate a List of Outlook CommandBar IDs

You can use the following Microsoft Excel VBA sample code to generate a spreadsheet that contains a list of Outlook commands and their corresponding CommandBar control IDs. The code adds an Excel AutoFilter to the spreadsheet so that you can easily find the ID that you are looking for.

To set up this utility:

  1. Start Excel. Make sure that you are in a new Excel workbook.
  2. On the Tools menu, point to Macro, and then click Visual Basic Editor.
  3. In the editor's Project Explorer window, double-click ThisWorkbook to open a code window.
  4. In the code window, enter the following code:

    Option Explicit
    Dim oOutApp As Outlook.Application
    Dim I As Long
    Dim iRowCount As Long
    Dim oItm As Object ' so it'll handle varying item types
    Dim oSheet As Excel.Worksheet
    Dim oNS As Outlook.NameSpace
    Dim oFld As Outlook.MAPIFolder
    
    Sub GetOutlookCommandBarIDs()
    
    If MsgBox("This will clear the current worksheet, OK to continue?", vbOKCancel) = 1 Then
       
       Cells.Select
       Selection.ClearContents
       
       iRowCount = 0
       Set oSheet = ActiveSheet
       Set oOutApp = New Outlook.Application
       Set oNS = oOutApp.Session
       
       Set oItm = oOutApp.CreateItem(olMailItem)
       GetInspectorIDs oItm, "Mail Message"
       Set oItm = oOutApp.CreateItem(olPostItem)
       GetInspectorIDs oItm, "Post"
       Set oItm = oOutApp.CreateItem(olContactItem)
       GetInspectorIDs oItm, "Contact"
       Set oItm = oOutApp.CreateItem(olDistributionListItem)
       GetInspectorIDs oItm, "Distribution List"
       Set oItm = oOutApp.CreateItem(olAppointmentItem)
       GetInspectorIDs oItm, "Appointment"
       Set oItm = oOutApp.CreateItem(olTaskItem)
       GetInspectorIDs oItm, "Task"
       Set oItm = oOutApp.CreateItem(olJournalItem)
       GetInspectorIDs oItm, "Journal Entry"
       
       Set oFld = oNS.GetDefaultFolder(olFolderInbox)
       GetExplorerIDs oFld, "Mail Folder"
       Set oFld = oNS.GetDefaultFolder(olFolderContacts)
       GetExplorerIDs oFld, "Contact Folder"
       Set oFld = oNS.GetDefaultFolder(olFolderCalendar)
       GetExplorerIDs oFld, "Calendar Folder"
       Set oFld = oNS.GetDefaultFolder(olFolderTasks)
       GetExplorerIDs oFld, "Task Folder"
       Set oFld = oNS.GetDefaultFolder(olFolderJournal)
       GetExplorerIDs oFld, "Journal Folder"
       Set oFld = oNS.GetDefaultFolder(olFolderNotes)
       GetExplorerIDs oFld, "Notes Folder"
       
       Selection.AutoFilter
       Cells.Select
       Cells.EntireColumn.AutoFit
       Range("A1").Select
    
       MsgBox "The spreadsheet is complete."
       
    End If
    
    End Sub
    
    
    Sub GetInspectorIDs(oItm, sType As String)
       Dim oCBs As Office.CommandBars
       Dim oCtl As Office.CommandBarControl
       Set oCBs = oItm.GetInspector.CommandBars
       For I = 1 To 35000
          Set oCtl = oCBs.FindControl(, I)
          If Not (oCtl Is Nothing) Then
             iRowCount = iRowCount + 1
             oSheet.Cells(iRowCount, 1) = "Inspector"
             oSheet.Cells(iRowCount, 2) = sType
             oSheet.Cells(iRowCount, 3) = oCtl.Parent.Name
             oSheet.Cells(iRowCount, 4) = oCtl.Caption
             oSheet.Cells(iRowCount, 5) = CStr(I)
          End If
       Next
    End Sub
    
    
    Sub GetExplorerIDs(oFld As Outlook.MAPIFolder, sType As String)
       Dim oCBs As Office.CommandBars
       Dim sFilter As String
       Dim oCtl As Office.CommandBarControl
       Set oCBs = oFld.GetExplorer.CommandBars
       For I = 1 To 35000
          Set oCtl = oCBs.FindControl(, I)
          If Not (oCtl Is Nothing) Then
             iRowCount = iRowCount + 1
             oSheet.Cells(iRowCount, 1) = "Explorer"
             oSheet.Cells(iRowCount, 2) = sType
             oSheet.Cells(iRowCount, 3) = oCtl.Parent.Name
             oSheet.Cells(iRowCount, 4) = oCtl.Caption
             oSheet.Cells(iRowCount, 5) = CStr(I)
          End If
       Next
    End Sub
                        
  5. On the Tools menu, click References. In the list of available object libraries, click Microsoft Outlook 10.0 Object Library, and then click OK.
  6. Close the Visual Basic Editor.
  7. Save the Excel workbook so that you have it for future use.

To generate the list of IDs:

  1. Make sure that the Excel security settings allow the macro to run. On the Tools menu, click Security, and then make sure that your settings are set to Medium or Low, at least temporarily. If you change the settings from High, you must restart Excel.
  2. Open the workbook that you created when you set up the Excel utility.
  3. On the Tools menu, point to Macro, and then click Macros. Click the GetOutlookCommandBarIDs macro, and then click Run.
  4. Wait while the spreadsheet is generated. This will take at least a couple of minutes. After the macro finishes runnning, you receive a message that states, "The spreadsheet is complete."
  5. After the spreadsheet is generated, save the workbook so that you do not have to run the macro again.

To use the spreadsheet, use the AutoFilter feature at the top to find the CommandBar ID that you are looking for. For example, in cell A1 you can select a command on an Explorer or Inspector object; in cell B1, you can then select the type of item or folder that contains the command.


REFERENCES

For additional information about available resources and answersto commonly asked questions about Microsoft Outlook solutions, click the article numbers below to view the articles in the Microsoft Knowledge Base:

146636 OL2000: Questions About Custom Forms and Outlook Solutions


287530 OL2002: Questions About Custom Forms and Outlook Solutions



Additional query words: OutSol OutSol2000 OutSol2002 OL2K

Keywords: kbinfo KB201095