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

适用范围:yesVisual Studio noVisual Studio for Mac noVisual Studio Code

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

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

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

注意

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

本演练演示以下任务:

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

  • 创建自定义功能区 UI。

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

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

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

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

注意

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

先决条件

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

创建项目

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

创建新项目的步骤

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

    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 外接程序能够跟踪与每封打开的电子邮件关联的自定义任务窗格,请创建一个用于包装 和 CustomTaskPane 对象的对的Inspector自定义类。 此类为每封电子邮件创建新的自定义任务窗格对象,并在关闭相应的电子邮件时删除自定义任务窗格。

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

  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 外接程序时测试行为。

后续步骤

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

另请参阅