演练:为 Outlook 中的电子邮件显示自定义任务窗格
此演练演示如何为创建或打开的每个电子邮件显示一个唯一的自定义任务窗格实例。 用户可以使用每个电子邮件的功能区上的按钮来显示或隐藏自定义任务窗格。
**适用于:**本主题中的信息适用于 Outlook 2007 和 Outlook 2010 的应用程序级项目。有关更多信息,请参见按 Office 应用程序和项目类型提供的功能。
若要为多个资源管理器或检查器窗口显示自定义任务窗格,必须为每个打开的窗口创建一个自定义任务窗格实例。 有关自定义任务窗格在 Outlook 窗口中的行为的更多信息,请参见自定义任务窗格概述。
提示
此演练分几个小节呈现外接程序代码,以便能够更加方便地讨论代码背后的逻辑。 若要查看在此演练中编辑的每个文件的完整内容,请参见如何:为 Outlook 中的电子邮件显示自定义任务窗格。
本演练阐释了以下任务:
设计自定义任务窗格的用户界面 (UI)。
创建自定义功能区 UI。
为电子邮件显示自定义功能区 UI。
创建一个类以管理检查器窗口和自定义任务窗格。
初始化和清理外接程序使用的资源。
将功能区切换按钮与自定义任务窗格同步。
提示
以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 您安装的 Visual Studio 版本以及使用的设置决定了这些元素。 有关更多信息,请参见 使用设置。
系统必备
您需要以下组件来完成本演练:
-
Visual Studio 2010 的一个版本,其中包含 Microsoft Office 开发工具。有关更多信息,请参见[将计算机配置为开发 Office 解决方案](bb398242\(v=vs.100\).md)。
- Microsoft Office Outlook 2007 或 Microsoft Outlook 2010。
有关相关视频演示,请参见 How Do I: Use Task Panes in Outlook?(如何实现:在 Outlook 中使用任务窗格?)。
创建项目
自定义任务窗格是在应用程序级外接程序中实现的。 从创建 Outlook 外接程序项目开始。
创建新项目
创建一个名为 OutlookMailItemTaskPane 的**“Outlook 外接程序”项目。 使用“Outlook 外接程序”**项目模板。 有关更多信息,请参见如何:在 Visual Studio 中创建 Office 项目。
Visual Studio 将打开 ThisAddIn.cs 或 ThisAddIn.vb 代码文件,并将**“OutlookMailItemTaskPane”项目添加到“解决方案资源管理器”**中。
设计自定义任务窗格的用户界面。
自定义任务窗格没有可视化设计器,但您可以设计具有所需 UI 的用户控件。 此外接程序中的自定义任务窗格具有一个简单的 UI,其中包含 TextBox 控件。 在本演练后面的部分中,您将把此用户控件添加到自定义任务窗格。
设计自定义任务窗格的用户界面
在**“解决方案资源管理器”中,单击“OutlookMailItemTaskPane”**项目。
在**“项目”菜单上,单击“添加用户控件”**。
在**“添加新项”对话框中,将用户控件的名称改为 TaskPaneControl,然后单击“添加”**。
该用户控件即在设计器中打开。
从**“工具箱”的“公共控件”选项卡中,将“TextBox”**控件拖到用户控件中。
设计功能区的用户界面
此外接程序的目的之一是为用户提供一种从每个电子邮件的功能区中隐藏或显示自定义任务窗格的方法。 若要提供用户界面,请创建一个显示切换按钮的自定义功能区 UI,用户可单击该按钮来显示或隐藏自定义任务窗格。
创建自定义功能区 UI
在**“项目”菜单上,单击“添加新项”**。
在**“添加新项”对话框中,选择“功能区(可视化设计器)”**。
将新功能区更名为 ManageTaskPaneRibbon,然后单击**“添加”**。
ManageTaskPaneRibbon.cs 或 ManageTaskPaneRibbon.vb 文件将在功能区设计器中打开,并显示一个默认选项卡和组。
在功能区设计器中,单击**“group1”**。
在**“属性”窗口中,将“Label”**属性设置为“任务窗格管理器”。
从**“工具箱”的“Office 功能区控件”选项卡中,将“ToggleButton”控件拖到“任务窗格管理器”**组上。
单击**“toggleButton1”**。
在**“属性”窗口中,将“Label”**属性设置为“显示任务窗格”。
为电子邮件显示自定义功能区用户界面
在此演练中创建的自定义任务窗格设计为仅为包含电子邮件的检查器窗口显示。 因此,设置属性以便仅为这些窗口显示自定义功能区 UI。
为电子邮件显示自定义功能区 UI
在功能区设计器中,单击**“ManageTaskPaneRibbon”**功能区。
在**“属性”窗口中,单击“RibbonType”旁边的下拉列表,然后选择“Microsoft.Outlook.Mail.Compose”和“Microsoft.Outlook.Mail.Read”**。
创建一个类以管理检查器窗口和自定义任务窗格
在某些情况下,外接程序必须确定哪个自定义任务窗格与特定的电子邮件相关联。 这些情况包括:
用户关闭电子邮件时。 在这种情况下,外接程序必须移除对应的自定义任务窗格,以确保外接程序使用的资源得到正确清理。
用户关闭自定义任务窗格时。 在这种情况下,外接程序必须更新电子邮件的功能区上切换按钮的状态。
用户单击功能区上的切换按钮时。 在这种情况下,外接程序必须隐藏或显示对应的任务窗格。
若要使外接程序能够跟踪哪个自定义任务窗格与每个打开的电子邮件相关联,请创建一个包装 Inspector 和 CustomTaskPane 对象对的自定义类。 此类为每个电子邮件创建一个新的自定义任务窗格对象,并在对应的电子邮件关闭时删除该自定义任务窗格。
创建一个类以管理检查器窗口和自定义任务窗格
在**“解决方案资源管理器”中,右击 ThisAddIn.cs 或 ThisAddIn.vb 文件,然后单击“查看代码”**。
将下面的语句添加到文件的顶部。
Imports System.Collections.Generic Imports Microsoft.Office.Tools Imports Office = Microsoft.Office.Core Imports Outlook = Microsoft.Office.Interop.Outlook
using Microsoft.Office.Tools;
将下面的代码添加到 ThisAddIn.cs 或 ThisAddIn.vb 文件中,放在 ThisAddIn 类的外部(对于 Visual C#,请在 OutlookMailItemTaskPane 命名空间内部添加此代码)。 InspectorWrapper 类管理 Inspector 和 CustomTaskPane 对象对。 在下面的步骤中,您将完成此类的定义。
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;
在上一步中添加的代码后面,添加以下构造函数。 该构造函数创建并初始化一个新的、与传入的 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); }
在上一步中添加的代码后面,添加下列方法。 此方法是 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; }
在上一步中添加的代码后面,添加下列方法。 此方法是 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; }
在上一步中添加的代码后面,添加下列代码。 在此演练的后面,您将从自定义功能区 UI 内的方法中调用此属性,以显示或隐藏自定义任务窗格。
Public ReadOnly Property CustomTaskPane() As CustomTaskPane Get Return taskPane End Get End Property End Class
public CustomTaskPane CustomTaskPane { get { return taskPane; } } }
初始化和清理外接程序使用的资源
将代码添加到 ThisAddIn 类,以便在加载外接程序时初始化外接程序,并在卸载外接程序时清理外接程序使用的资源。 通过为 NewInspector 事件设置一个事件处理程序,并将全部现有的电子邮件传递到此事件处理程序,将可以初始化外接程序。 卸载外接程序时,请分离事件处理程序,并清理该外接程序使用的对象。
初始化和清理外接程序使用的资源
在 ThisAddIn.cs 或 ThisAddIn.vb 文件中,找到 ThisAddIn 类的定义。
将以下声明添加到 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;
用下面的代码替换 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); } }
用下面的代码替换 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; }
将以下 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)); } }
将以下属性添加到 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 事件处理程序。
将自定义任务窗格与切换按钮同步
在功能区设计器中,双击**“显示任务窗格”**切换按钮。
Visual Studio 将自动生成一个名为 toggleButton1_Click 的事件处理程序,该事件处理程序可处理切换按钮的 Click 事件。 Visual Studio 还会在代码编辑器中打开 ManageTaskPaneRibbon.cs 或 ManageTaskPaneRibbon.vb 文件。
将下列语句添加到 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;
用下面的代码替换 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 将打开,并且将加载外接程序。 该外接程序将为打开的每个电子邮件显示一个唯一的自定义任务窗格实例。 创建若干新电子邮件以测试代码。
测试外接程序
按 F5。
在 Outlook 中,单击**“新建”**以创建新电子邮件。
在该电子邮件的功能区上,单击**“外接程序”选项卡,然后单击“显示任务窗格”**按钮。
验证是否为该电子邮件显示了标题为**“我的任务窗格”**的任务窗格。
在该任务窗格的文本框中键入“第一个任务窗格”。
关闭任务窗格。
验证**“显示任务窗格”**按钮的状态是否发生变化,以使其不再处于按下状态。
再次单击**“显示任务窗格”**按钮。
验证任务窗格是否打开,以及文本框是否仍然包含字符串“第一个任务窗格”。
在 Outlook 中,单击**“新建”**以创建另一个电子邮件。
在该电子邮件的功能区上,单击**“外接程序”选项卡,然后单击“显示任务窗格”**按钮。
验证是否为该电子邮件显示了标题为**“我的任务窗格”**的任务窗格,并且此任务窗格中的文本框为空。
在该任务窗格的文本框中键入“第二个任务窗格”。
将焦点切换到第一封电子邮件。
验证与此电子邮件关联的任务窗格是否在文本框中仍然显示“第一个任务窗格”。
此外接程序还能处理您可尝试的更高级的方案。 例如,可以测试在使用**“下一项”和“上一项”**按钮查看电子邮件时的行为。 还可以测试在卸载外接程序,打开若干电子邮件然后重新加载外接程序时的行为。
后续步骤
可从以下主题中了解有关如何创建自定义任务窗格的更多信息:
在适用于其他应用程序的外接程序中创建自定义任务窗格。 有关支持自定义任务窗格的应用程序的更多信息,请参见 自定义任务窗格概述。
使用自定义任务窗格实现 Microsoft Office 应用程序自动化。 有关更多信息,请参见演练:从自定义任务窗格自动化应用程序。
在 Excel 中创建一个可用于隐藏或显示自定义任务窗格的功能区按钮。 有关更多信息,请参见演练:将自定义任务窗格与功能区按钮同步。