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

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

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

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

注释

本演练在小部分中演示 VSTO 外接程序代码,以便更轻松地讨论代码背后的逻辑。

本演练阐释了以下任务:

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

  • 创建自定义功能区用户界面。

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

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

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

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

注释

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

先决条件

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

创建项目

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

创建新项目

  1. 创建名为 OutlookMailItemTaskPaneOutlook 外接程序项目。 使用 Outlook 外接程序 项目模板。 有关详细信息,请参阅 如何:在 Visual Studio 中创建 Office 项目

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

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

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

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

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

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

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

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

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

设计Ribbon用户界面

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

创建一个自定义功能区 UI

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

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

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

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

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

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

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

  7. 单击 toggleButton1

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

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

在本演练中创建的自定义任务窗格旨在仅在包含电子邮件消息的检查器窗口中显示。 因此,设置属性,使自定义功能区 (Ribbon) 用户界面仅在这些窗口中显示。

要在电子邮件中显示自定义功能区 UI

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

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

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

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

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

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

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

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

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

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

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

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

    public class InspectorWrapper
    {
        private Outlook.Inspector inspector;
        private CustomTaskPane taskPane;
    
  4. 在上一步中添加的代码后添加以下构造函数。 此构造函数创建并初始化与 Inspector 传入的对象关联的新自定义任务窗格。 在 C# 中,构造函数还会将事件处理程序 Close 附加到对象的事件 InspectorVisibleChanged 对象的事件 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. 在上一步中添加的代码后添加以下方法。 此方法是InspectorWrapper类中CustomTaskPane对象的VisibleChanged事件的事件处理程序。 每当用户打开或关闭自定义任务窗格时,此代码将更新切换按钮的状态。

    void TaskPane_VisibleChanged(object sender, EventArgs e)
    {
        Globals.Ribbons[inspector].ManageTaskPaneRibbon.toggleButton1.Checked = 
            taskPane.Visible;
    }
    
  6. 在上一步中添加的代码后添加以下方法。 此方法是Inspector对象中Close事件的事件处理程序,Inspector对象包含当前的电子邮件消息。 当电子邮件关闭时,事件处理程序释放资源。 事件处理程序还会从 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 外接程序,并在卸载 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 类。 此属性将类的ThisAddIn专用字段公开给类外部的inspectorWrappersValue代码。

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

Checkpoint

生成项目以确保其编译时不会出现错误。

构建项目

  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. 在任务窗格中,在文本框中键入 “第一个任务”窗格

  5. 关闭任务窗格。

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

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

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

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

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

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

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

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

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

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

后续步骤

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