演练:在 Outlook 中使用电子邮件显示自定义任务窗格

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

适用于: 本主题中的信息适用于 Outlook 的 VSTO 外接程序项目。 有关详细信息,请参阅办公室应用程序和项目类型提供的功能。

若要使用多个资源管理器或检查器窗口显示自定义任务窗格,则必须为打开的每个窗口创建自定义任务窗格的实例。 有关 Outlook 窗口中自定义任务窗格的行为的详细信息,请参阅 自定义任务窗格

注意

本演练分小段展示 VSTO 外接程序代码以便更容易讨论代码背后的逻辑。

本演练阐释了以下任务:

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

  • 创建自定义功能区 UI。

  • 显示包含电子邮件的自定义功能区 UI。

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

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

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

注意

以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 这些元素取决于你所使用的 Visual Studio 版本和你所使用的设置。 有关详细信息,请参阅个性化设置 Visual Studio IDE

先决条件

你需要满足以下条件才能完成本演练:

创建项目

自定义任务窗格在 VSTO 外接程序中实现。首先创建适用于 Outlook 的 VSTO 外接程序项目。

创建新项目

  1. 创建名为 OutlookMailItemTaskPane 的“Outlook 外接程序” 项目。 使用“Outlook 外接程序” 项目模板。 有关详细信息,请参阅“如何:在 Visual Studio 中创建办公室项目。

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

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

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

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

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

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

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

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

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

设计功能区用户界面

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

若要创建自定义功能区 UI

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

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

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

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

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

  5. 在“属性” 窗口中,将“Label”属性 设置为 Task Pane Manager

  6. 从“工具箱” 的“Office 功能区控件” 选项卡中,将 ToggleButton 控件拖到“Task Pane Manager” 组。

  7. 单击“toggleButton1”

  8. 在“属性” 窗口中,将“Label”属性 设置为 Show Task Pane

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

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

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

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

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

创建用于管理检查器窗口和自定义任务窗格的类

在某些情况下,VSTO 外接程序必须标识与特定电子邮件关联的自定义任务窗格。 这些情况包括以下几种:

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

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

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

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

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

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

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

    using Microsoft.Office.Tools;
    
  3. 将以下代码添加到 类外部的 ThisAddIn.cs ThisAddIn.vb ThisAddIn 文件中(对于 Visual C#,将此代码添加入 OutlookMailItemTaskPane 命名空间)。 InspectorWrapper 类管理一对 InspectorCustomTaskPane 对象。 你将在以下步骤中完成此类的定义。

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

    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. 将以下方法添加在上一步添加的代码后。 此方法是 VisibleChanged 类中包含的 CustomTaskPane 对象的 InspectorWrapper 事件。 每当用户打开或关闭自定义任务窗格时,此代码将更新切换按钮的状态。

    void TaskPane_VisibleChanged(object sender, EventArgs e)
    {
        Globals.Ribbons[inspector].ManageTaskPaneRibbon.toggleButton1.Checked = 
            taskPane.Visible;
    }
    
  6. 将以下方法添加在上一步添加的代码后。 此方法是包含当前电子邮件的对象事件的Inspector事件处理程序Close。 当电子邮件关闭时,事件处理程序释放资源。 事件处理程序还会从 CustomTaskPanes 集合删除当前的自定义任务窗格。 这有助于防止打开下一封电子邮件时自定义任务窗格的多个实例。

    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 CustomTaskPane CustomTaskPane
        {
            get
            {
                return taskPane;
            }
        }
    }
    

初始化和清理加载项使用的资源

添加代码到 ThisAddIn 类以便在加载 VSTO 外接程序对其进行初始化,并在卸载 VSTO 外接程序时清理其使用的资源。 通过设置事件的 NewInspector 事件处理程序并将所有现有电子邮件传递给此事件处理程序来初始化 VSTO 外接程序。 VSTO 外接程序卸载时,分离事件处理程序并清理 VSTO 外接程序使用的对象。

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

  1. ThisAddIn.csThisAddIn.vb 文件中,找到 ThisAddIn 类的定义。

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

    • inspectorWrappersValue 字段包含由 VSTO 外接程序管理的所有 InspectorInspectorWrapper 对象。

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

      private Dictionary<Outlook.Inspector, InspectorWrapper> inspectorWrappersValue =
          new Dictionary<Outlook.Inspector, InspectorWrapper>();
      private Outlook.Inspectors inspectors;
      

  3. ThisAddIn_Startup 方法替换为以下代码。 此代码将事件处理程序附加到 NewInspector 事件,并且它将每个现有 Inspector 对象传递到事件处理程序。 如果用户在 Outlook 正在运行后加载 VSTO 外接程序,VSTO 外接程序将使用此信息为所有已打开的电子邮件创建自定义任务窗格。

    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 事件处理程序,并清理 VSTO 外接程序使用的对象。

    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 对象的实例,用于管理电子邮件与相应任务窗格之间的关系。

    void Inspectors_NewInspector(Outlook.Inspector Inspector)
    {
        if (Inspector.CurrentItem is Outlook.MailItem)
        {
            inspectorWrappersValue.Add(Inspector, new InspectorWrapper(Inspector));
        }
    }
    
  6. ThisAddIn 类添加以下属性。 此属性将私有 inspectorWrappersValue 字段公开为 ThisAddIn 类外部的代码。

    public Dictionary<Outlook.Inspector, InspectorWrapper> InspectorWrappers
    {
        get
        {
            return inspectorWrappersValue;
        }
    }
    

检查点

生成项目以确保它在编译时没有错误。

若要生成你的项目

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

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

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

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

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

    Visual Studio 会自动生成名为 toggleButton1_Click的事件处理程序,它将处理切换按钮的 Click 事件。 Visual Studio 还将打开代码编辑器中的 ManageTaskPaneRibbon.csManageTaskPaneRibbon.vb 文件。

  2. 将以下语句添加到 ManageTaskPaneRibbon.csManageTaskPaneRibbon.vb 文件的顶部。

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

    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 并且加载 VSTO 外接程序。 VSTO 外接程序显示自定义任务窗格的唯一实例,其中包含打开的每个电子邮件。 创建多个新电子邮件以测试代码。

若要测试 VSTO 外接程序

  1. 按 F5

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

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

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

  4. 在任务窗格中,在文本框中键入 First task pane

  5. 关闭任务窗格。

    验证“显示任务窗格” 的状态是否更改,以便此按钮不再按下。

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

    验证任务窗格是否打开,并且文本框中是否仍然包含字符串 First task pane

  7. 在 Outlook 中,单击“新建以创建第二封电子邮件。

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

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

  9. 在任务窗格中,在文本框中键入 Second task pane

  10. 将焦点更改为第一封电子邮件。

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

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

后续步骤

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

  • 为其他应用程序在 VSTO 外接程序中创建自定义任务窗格。 有关支持自定义任务窗格的应用程序的详细信息,请参阅 自定义任务窗格

  • 通过使用自定义任务窗格自动化 Microsoft Office 应用程序。 有关详细信息,请参阅 演练:从自定义任务窗格自动执行应用程序。

  • 在 Excel 中创建一个可用于隐藏或显示自定义任务窗格的功能区按钮。 有关详细信息,请参阅 演练:将自定义任务窗格与功能区按钮同步。