演练:为 Outlook 中的电子邮件显示自定义任务窗格

更新:2007 年 11 月

适用对象

本主题中的信息仅适用于指定的 Visual Studio Tools for Office 项目和 Microsoft Office 应用程序。

项目类型

  • 应用程序级项目

Microsoft Office 应用程序

  • Outlook 2007

有关更多信息,请参见按应用程序和项目类型提供的功能

此演练演示如何为创建或打开的每个电子邮件显示一个唯一的自定义任务窗格实例。用户可以使用每个电子邮件的功能区上的按钮来显示或隐藏自定义任务窗格。

若要为多个资源管理器或检查器窗口显示自定义任务窗格,必须为每个打开的窗口创建一个自定义任务窗格实例。有关自定义任务窗格在 Outlook 窗口中的行为的更多信息,请参见自定义任务窗格概述

Bb296010.alert_note(zh-cn,VS.90).gif说明:

此演练分几个小节呈现外接程序代码,以便能够更加方便地讨论代码背后的逻辑。若要查看在此演练中编辑的每个文件的完整内容,请参见如何:为 Outlook 中的电子邮件显示自定义任务窗格

本演练阐释以下任务:

  • 设计自定义任务窗格的用户界面 (UI)。

  • 创建自定义功能区 UI。

  • 为电子邮件显示自定义功能区 UI。

  • 创建一个类以管理检查器窗口和自定义任务窗格。

  • 初始化和清理外接程序使用的资源。

  • 将功能区切换按钮与自定义任务窗格同步。

Bb296010.alert_note(zh-cn,VS.90).gif说明:

以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。您安装的 Visual Studio 版本以及使用的设置决定了这些元素。有关更多信息,请参见 Visual Studio 设置

先决条件

您需要以下组件来完成本演练:

  • Visual Studio Tools for Office(Visual Studio 2008 专业版 和 Visual Studio Team System 的可选组件)。

  • Microsoft Office Outlook 2007。

默认情况下,Visual Studio Tools for Office 随列出的 Visual Studio 版本一起安装。若要检查它是否已安装,请参见安装 Visual Studio Tools for Office

创建项目

自定义任务窗格是在应用程序级外接程序中实现的。从创建 Outlook 2007 外接程序项目开始。

创建新项目

  • 创建一个名为 OutlookMailItemTaskPane 的“Outlook 外接程序”项目。使用适用于 2007 Microsoft Office system 的“Outlook 外接程序”项目模板。有关更多信息,请参见如何:创建 Visual Studio Tools for Office 项目

    Visual Studio 将打开 ThisAddIn.cs 或 ThisAddIn.vb 代码文件,并将“OutlookMailItemTaskPane”项目添加到“解决方案资源管理器”中。

设计自定义任务窗格的用户界面。

自定义任务窗格没有可视化设计器,但您可以设计具有所需 UI 的用户控件。此外接程序中的自定义任务窗格具有一个简单的 UI,其中包含 TextBox 控件。在此演练后面的部分中,您将把此用户控件添加到自定义任务窗格。

设计自定义任务窗格的用户界面

  1. 在“解决方案资源管理器”中,单击“OutlookMailItemTaskPane”项目。

  2. 在“项目”菜单上单击“添加用户控件”。

  3. 在“添加新项”对话框中,将用户控件的名称改为 TaskPaneControl,然后单击“添加”。

    该用户控件即在设计器中打开。

  4. 从“工具箱”的“公共控件”选项卡中,将“TextBox”控件拖到用户控件中。

设计功能区的用户界面

此外接程序的目的之一是为用户提供一种从每个电子邮件的功能区中隐藏或显示自定义任务窗格的方法。若要提供用户界面,请创建一个显示切换按钮的自定义功能区 UI,用户可单击该按钮来显示或隐藏自定义任务窗格。

创建自定义功能区 UI

  1. 在“项目”菜单上单击“添加新项”。

  2. 在“添加新项”对话框中,选择“功能区(可视化设计器)”。

  3. 将新功能区更名为 ManageTaskPaneRibbon,然后单击“添加”。

    ManageTaskPaneRibbon.cs 或 ManageTaskPaneRibbon.vb 文件将在功能区设计器中打开,并显示一个默认选项卡和组。

  4. 在功能区设计器中,单击“group1”。

  5. 在“属性”窗口中,将“Label”属性设置为“任务窗格管理器”。

  6. 从“工具箱”的“Office 功能区控件”选项卡中,将“ToggleButton”控件拖到“任务窗格管理器”组上。

  7. 单击“toggleButton1”。

  8. 在“属性”窗口中,将“Label”属性设置为“显示任务窗格”。

为电子邮件显示自定义功能区用户界面

在此演练中创建的自定义任务窗格设计为仅为包含电子邮件的检查器窗口显示。因此,设置属性以便仅为这些窗口显示自定义功能区 UI。

为电子邮件显示自定义功能区 UI

  1. 在功能区设计器中,单击“ManageTaskPaneRibbon”功能区。

  2. 在“属性”窗口中,单击“RibbonType”旁边的下拉列表,然后选择“Microsoft.Outlook.Mail.Compose”和“Microsoft.Outlook.Mail.Read”。

创建一个类以管理检查器窗口和自定义任务窗格

在某些情况下,外接程序必须确定哪个自定义任务窗格与特定的电子邮件相关联。这些情况包括:

  • 用户关闭电子邮件时。在这种情况下,外接程序必须移除对应的自定义任务窗格,以确保外接程序使用的资源得到正确清理。

  • 用户关闭自定义任务窗格时。在这种情况下,外接程序必须更新电子邮件的功能区上切换按钮的状态。

  • 用户单击功能区上的切换按钮时。在这种情况下,外接程序必须隐藏或显示对应的任务窗格。

若要使外接程序能够跟踪哪个自定义任务窗格与每个打开的电子邮件相关联,请创建一个包装 InspectorCustomTaskPane 对象对的自定义类。此类为每个电子邮件创建一个新的自定义任务窗格对象,并在对应的电子邮件关闭时删除该自定义任务窗格。

创建一个类以管理检查器窗口和自定义任务窗格

  1. 在“解决方案资源管理器”中,右击 ThisAddIn.cs 或 ThisAddIn.vb 文件,然后单击“查看代码”。

  2. 将下面的语句添加到文件的顶部。

    Imports System.Collections.Generic
    Imports Microsoft.Office.Tools
    Imports Office = Microsoft.Office.Core
    Imports Outlook = Microsoft.Office.Interop.Outlook
    
    using Microsoft.Office.Tools;
    
  3. 将下面的代码添加到 ThisAddIn.cs 或 ThisAddIn.vb 文件中,放在 ThisAddIn 类的外部(对于 Visual C#,请在 OutlookMailItemTaskPane 命名空间内部添加此代码)。InspectorWrapper 类管理 InspectorCustomTaskPane 对象对。在下面的步骤中,您将完成此类的定义。

    Public Class InspectorWrapper
        Private inspector As Outlook.Inspector
        Private WithEvents inspectorEvents As Outlook.InspectorEvents_Event
        Private WithEvents taskPane As CustomTaskPane
    
    public class InspectorWrapper
    {
        private Outlook.Inspector inspector;
        private CustomTaskPane taskPane;
    
  4. 在上一步中添加的代码后面,添加以下构造函数。此构造函数创建并初始化与传入的 Inspector 对象关联的一个新自定义任务窗格。在 C# 中,该构造函数还将事件处理程序附加到 Inspector 对象的 Close 事件,并附加到 CustomTaskPane 对象的 VisibleChanged 事件。

    Public Sub New(ByVal Inspector As Outlook.Inspector)
        Me.inspector = Inspector
        inspectorEvents = TryCast(Me.inspector, Outlook.InspectorEvents_Event)
        taskPane = Globals.ThisAddIn.CustomTaskPanes.Add(New TaskPaneControl(), _
            "My task pane", Inspector)
    End Sub
    
    public InspectorWrapper(Outlook.Inspector Inspector)
    {
        inspector = Inspector;
        ((Outlook.InspectorEvents_Event)inspector).Close +=
            new Outlook.InspectorEvents_CloseEventHandler(InspectorWrapper_Close);
    
        taskPane = Globals.ThisAddIn.CustomTaskPanes.Add(
            new TaskPaneControl(), "My task pane", inspector);
        taskPane.VisibleChanged += new EventHandler(TaskPane_VisibleChanged);
    }
    
  5. 在上一步中添加的代码后面,添加下列方法。此方法是 CustomTaskPane 对象的 VisibleChanged 事件的事件处理程序,该对象包含在 InspectorWrapper 类中。每当用户打开或关闭自定义任务窗格时,此代码将更新切换按钮的状态。

    Private Sub TaskPane_VisibleChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles taskPane.VisibleChanged
        Globals.Ribbons(inspector).ManageTaskPaneRibbon.ToggleButton1.Checked = taskPane.Visible
    End Sub
    
    void TaskPane_VisibleChanged(object sender, EventArgs e)
    {
        Globals.Ribbons[inspector].ManageTaskPaneRibbon.toggleButton1.Checked = 
            taskPane.Visible;
    }
    
  6. 在上一步中添加的代码后面,添加下列方法。此方法是 Inspector 对象的 Close 事件的事件处理程序,该对象包含当前电子邮件。该事件处理程序在电子邮件关闭时释放资源。该事件处理程序还会从 CustomTaskPanes 集合中移除当前自定义任务窗格。这可以帮助防止在下一封电子邮件打开时出现自定义任务窗格的多个实例。

    Sub InspectorWrapper_Close() Handles inspectorEvents.Close
        If Not (taskPane Is Nothing) Then
            Globals.ThisAddIn.CustomTaskPanes.Remove(taskPane)
        End If
    
        taskPane = Nothing
        Globals.ThisAddIn.InspectorWrappers.Remove(inspector)
        RemoveHandler inspectorEvents.Close, AddressOf InspectorWrapper_Close
        inspector = Nothing
    End Sub
    
    void InspectorWrapper_Close()
    {
        if (taskPane != null)
        {
            Globals.ThisAddIn.CustomTaskPanes.Remove(taskPane);
        }
    
        taskPane = null;
        Globals.ThisAddIn.InspectorWrappers.Remove(inspector);
        ((Outlook.InspectorEvents_Event)inspector).Close -=
            new Outlook.InspectorEvents_CloseEventHandler(InspectorWrapper_Close);
        inspector = null;
    }
    
  7. 在上一步中添加的代码后面,添加下列代码。在此演练的后面,您将从自定义功能区 UI 内的方法中调用此属性,以显示或隐藏自定义任务窗格。

        Public ReadOnly Property CustomTaskPane() As CustomTaskPane
            Get
                Return taskPane
            End Get
        End Property
    End Class
    
        public CustomTaskPane CustomTaskPane
        {
            get
            {
                return taskPane;
            }
        }
    }
    

初始化和清理外接程序使用的资源

将代码添加到 ThisAddIn 类,以便在加载外接程序时初始化外接程序,并在卸载外接程序时清理外接程序使用的资源。通过为 NewInspector 事件设置一个事件处理程序,并将全部现有的电子邮件传递到此事件处理程序,将可以初始化外接程序。卸载外接程序时,请分离事件处理程序,并清理该外接程序使用的对象。

初始化和清理外接程序使用的资源

  1. 在 ThisAddIn.cs 或 ThisAddIn.vb 文件中,找到 ThisAddIn 类的定义。

  2. 将以下声明添加到 ThisAddIn 类中:

    • inspectorWrappersValue 字段包含外接程序管理的所有 Inspector 和 InspectorWrapper 对象。

    • inspectors 字段保留对当前 Outlook 实例中检查器窗口集合的引用。此引用可防止垃圾回收器释放包含 NewInspector 事件的事件处理程序的内存,您将在下一步中声明该事件。

    Private inspectorWrappersValue As New Dictionary(Of Outlook.Inspector, InspectorWrapper)
    Private WithEvents inspectors As Outlook.Inspectors
    
    private Dictionary<Outlook.Inspector, InspectorWrapper> inspectorWrappersValue =
        new Dictionary<Outlook.Inspector, InspectorWrapper>();
    private Outlook.Inspectors inspectors;
    
  3. 用下面的代码替换 ThisAddIn_Startup 方法。此代码将事件处理程序附加到 NewInspector 事件,并将每个现有的 Inspector 对象传递到该事件处理程序。如果用户在 Outlook 已运行后加载外接程序,该外接程序将使用此信息为已经打开的所有电子邮件创建自定义任务窗格。

    Private Sub ThisAddIn_Startup(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles Me.Startup
    
        inspectors = Me.Application.Inspectors
        Dim inspector As Outlook.Inspector
        For Each inspector In inspectors
            Inspectors_NewInspector(inspector)
        Next inspector
    End Sub
    
    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        inspectors = this.Application.Inspectors;
        inspectors.NewInspector +=
            new Outlook.InspectorsEvents_NewInspectorEventHandler(
            Inspectors_NewInspector);
    
        foreach (Outlook.Inspector inspector in inspectors)
        {
            Inspectors_NewInspector(inspector);
        }
    }
    
  4. 用下面的代码替换 ThisAddIn_ShutDown 方法。此代码将分离 NewInspector 事件处理程序,并清理外接程序使用的对象。

    Private Sub ThisAddIn_Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles Me.Shutdown
    
        RemoveHandler inspectors.NewInspector, AddressOf Inspectors_NewInspector
        inspectors = Nothing
        inspectorWrappersValue = Nothing
    End Sub
    
    private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
    {
        inspectors.NewInspector -=
            new Outlook.InspectorsEvents_NewInspectorEventHandler(
            Inspectors_NewInspector);
        inspectors = null;
        inspectorWrappersValue = null;
    }
    
  5. 将以下 NewInspector 事件处理程序添加到 ThisAddIn 类。如果新的 Inspector 包含电子邮件,该方法将创建新 InspectorWrapper 对象的实例,以便管理电子邮件和对应任务窗格之间的关系。

    Sub Inspectors_NewInspector(ByVal Inspector As Outlook.Inspector) _
        Handles inspectors.NewInspector
    
        If TypeOf Inspector.CurrentItem Is Outlook.MailItem Then
            inspectorWrappersValue.Add(Inspector, New InspectorWrapper(Inspector))
        End If
    End Sub
    
    void Inspectors_NewInspector(Outlook.Inspector Inspector)
    {
        if (Inspector.CurrentItem is Outlook.MailItem)
        {
            inspectorWrappersValue.Add(Inspector, new InspectorWrapper(Inspector));
        }
    }
    
  6. 将以下属性添加到 ThisAddIn 类中。此属性向 ThisAddIn 类外部的代码公开私有 inspectorWrappersValue 字段。

    Public ReadOnly Property InspectorWrappers() As Dictionary(Of Outlook.Inspector, InspectorWrapper)
        Get
            Return inspectorWrappersValue
        End Get
    End Property
    
    public Dictionary<Outlook.Inspector, InspectorWrapper> InspectorWrappers
    {
        get
        {
            return inspectorWrappersValue;
        }
    }
    

检查点

生成项目以确保它在编译时不出错。

生成项目

  • 在“解决方案资源管理器”中,右击“OutlookMailItemTaskPane”项目,然后单击“生成”。验证项目是否在编译时未出错。

将功能区切换按钮与自定义任务窗格同步

当任务窗格可见时,切换按钮将显示为按下状态,当任务窗格隐藏时,该按钮将显示为未按下状态。若要将按钮的状态与自定义任务窗格同步,请修改切换按钮的 Click 事件处理程序。

将自定义任务窗格与切换按钮同步

  1. 在功能区设计器中,双击“显示任务窗格”切换按钮。

    Visual Studio Tools for Office 将自动生成一个名为 toggleButton1_Click 的事件处理程序,用于处理切换按钮的 Click 事件。此外,Visual Studio Tools for Office 还会在代码编辑器中打开 ManageTaskPaneRibbon.cs 或 ManageTaskPaneRibbon.vb 文件。

  2. 将下列语句添加到 ManageTaskPaneRibbon.cs 或 ManageTaskPaneRibbon.vb 文件的顶部。

    Imports Microsoft.Office.Tools.Ribbon
    Imports Outlook = Microsoft.Office.Interop.Outlook
    Imports Microsoft.Office.Tools
    
    using Outlook = Microsoft.Office.Interop.Outlook;
    using Microsoft.Office.Tools;
    
  3. 用下面的代码替换 toggleButton1_Click 事件处理程序。当用户单击切换按钮时,此方法将隐藏或显示与当前检查器窗口关联的自定义任务窗格。

    Private Sub ToggleButton1_Click(ByVal sender As System.Object, _
        ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) _
        Handles ToggleButton1.Click
    
        Dim inspector As Outlook.Inspector = e.Control.Context
        Dim inspectorWrapper As InspectorWrapper = Globals.ThisAddIn.InspectorWrappers(inspector)
        Dim taskPane As CustomTaskPane = inspectorWrapper.CustomTaskPane
        If Not (taskPane Is Nothing) Then
            taskPane.Visible = TryCast(sender, RibbonToggleButton).Checked
        End If
    End Sub
    
    private void toggleButton1_Click(object sender, RibbonControlEventArgs e)
    {
        Outlook.Inspector inspector = (Outlook.Inspector)e.Control.Context;
        InspectorWrapper inspectorWrapper = Globals.ThisAddIn.InspectorWrappers[inspector];
        CustomTaskPane taskPane = inspectorWrapper.CustomTaskPane;
        if (taskPane != null)
        {
            taskPane.Visible = ((RibbonToggleButton)sender).Checked;
        }
    }
    

测试项目

当您开始调试项目时,Outlook 将打开,并且将加载外接程序。该外接程序将为打开的每个电子邮件显示一个唯一的自定义任务窗格实例。创建若干新电子邮件以测试代码。

测试外接程序

  1. 按 F5。

  2. 在 Outlook 中,单击“新建”以创建新电子邮件。

  3. 在该电子邮件的功能区上,单击“外接程序”选项卡,然后单击“显示任务窗格”按钮。

    验证是否为该电子邮件显示了标题为“我的任务窗格”的任务窗格。

  4. 在该任务窗格的文本框中键入“第一个任务窗格”。

  5. 关闭任务窗格。

    验证“显示任务窗格”按钮的状态是否发生变化,以使其不再处于按下状态。

  6. 再次单击“显示任务窗格”按钮。

    验证任务窗格是否打开,以及文本框是否仍然包含字符串“第一个任务窗格”。

  7. 在 Outlook 中,单击“新建”以创建另一个电子邮件。

  8. 在该电子邮件的功能区上,单击“外接程序”选项卡,然后单击“显示任务窗格”按钮。

    验证是否为该电子邮件显示了标题为“我的任务窗格”的任务窗格,并且此任务窗格中的文本框为空。

  9. 在该任务窗格的文本框中键入“第二个任务窗格”。

  10. 将焦点切换到第一封电子邮件。

    验证与此电子邮件关联的任务窗格是否在文本框中仍然显示“第一个任务窗格”。

此外接程序还能处理您可尝试的更高级的方案。例如,可以测试在使用“下一项”和“上一项”按钮查看电子邮件时的行为。还可以测试在卸载外接程序,打开若干电子邮件然后重新加载外接程序时的行为。

后续步骤

可从以下主题中了解有关如何创建自定义任务窗格的更多信息:

请参见

任务

如何:向应用程序中添加自定义任务窗格

演练:从自定义任务窗格自动化应用程序

演练:将自定义任务窗格与功能区按钮同步

如何:为 Outlook 中的电子邮件显示自定义任务窗格

概念

自定义任务窗格概述

在多个应用程序窗口中管理自定义任务窗格

功能区概述

Outlook 对象模型概述

在运行时访问功能区