本专题概要

  • 引言
  • Outlook对象模型
  • 自定义Outlook窗体
  • 小结

一、引言
  在上一个专题中,为大家简单介绍了下如何创建Word解决方案的,所以本专题中将为大家介绍下Outlook相关的内容。我们从Visual Studio 2010 中Office节点下的模板中我们可以看到,Outlook只有外接程序的模板,并没有提供像Word或Excel这样的文档级的模板,所以VSTO没有为Outlook解决方案创建宿主项和宿主控件(Excel和Word中VSTO都为他们提供了宿主项和宿主控件,因为这些控件是文档级别的。对于宿主控件和宿主项的具体内容可以参考本系列的专题一)。为了能够更好地创建Outlook的解决方案,下面就具体介绍下Outlook对象模型。
二、Outlook对象模型
2.1 Application 对象
Application对象代表着Outlook应用程序,并且也是Outlook对象模型里的顶层对象(这点和Word和Excel是一样的)。在VSTO项目中要获得该对象的实例同样可以通过ThisAddIn类的Application字段来实现,具体代码为:Globals.ThisAddIn.Application或This.Application
2.2 NameSpace对象
Application对象的Session属性返回一个NameSpace对象,Session从字面上看是会话的意思,在Web开发中,我们可以从Session对象中获得保存的信息,同样,我们可以通过NameSpace对象来访问Outlook数据,比如当我们想获得收件箱里邮件数量时,此时就可以用到NameSpace对象,具体代码如下:

  • // 获得收件箱文件夹
  • Outlook.MAPIFolder Inbox =this.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
  • // 获得收件箱中邮件数量
  • int mailnumbers = Inbox.Items.Count;

2.3 Explorer对象
Explorer对象是显示Outlook中文件夹内容的窗口。文件夹包含项,例如邮件项,通俗点说,我们点击Outlook中的邮件或日历或联系人时,出现的窗口就是一个Explorer对象。
2.4 Inspector对象
Inspector对象是显示Outlook中每个项(例如单个电子邮件项、单个联系人项)的窗口。看到这里,有些朋友肯定会把Explorer对象与Inspector对象弄混淆,相信通过下面的图大家肯定可以完全明白两者的区别:

2.5 Outlook文件夹,即MAPIFolder对象
Outlook文件夹用来存储项(即邮件项,联系人项,任务项等),在Outlook中你可以创建自己的文件夹,然而Outlook中也提供了一些默认的文件夹。上面的这段代码: this.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox); 就是获得收件箱文件夹,如果你需要获得其他文件夹,可以通过改变OlDefaultFolders枚举值来获得。
2.6 Outlook项
Outlook里的项包含在文件夹里的。我们可以通过下面的代码来创建一个邮件项,如果要获得其他的Outlook项,可以通过修改Outlook.OlItemType枚举值来实现
// 创建邮件项            Outlook.MailItem mailItem = (Outlook.MailItem)this.Application.CreateItem(Outlook.OlItemType.olMailItem);
三、自定义Outlook窗体
  介绍了Outlook的这么多对象的,大家肯定很迫不及待地想知道使用VSTO的技术可以为Outlook实现什么样的功能呢?下面就用VSTO的技术来自定义Outlook的联系人窗体,在很多时候,我们都希望联系人的窗体中有关于父母的联系方式,然后在现有的Outlook界面中却没有这样的字段来给我们填写的,所以这里通过Form Region 的方式来实现自定义联系人窗体,我们需要在联系人窗体中加入输入父母姓名和联系方式的控件。
首先,我们需要创建Outlook窗体区域,创建步骤如下:

  • 右键项目,选择添加——>新建项目——>Outlook窗体区域
  • 选择”设计新的窗体区域“选项


  3. 窗体区域类型选择相邻,即把自定义的窗体附加到页面的底部。

4. 为窗体区域输入一个名字,并且设定在编辑模和阅读模式和中都显示窗体区域。

  5. 把我们的窗体区域嵌入在联系人窗体中。

完全以上一系列的步骤之后,VS会帮我们自动创建一个空的窗体区域,如果我们想修改刚才创建的窗体区域的设置,我们可以通过它的属性窗口中进行修改。

创建完窗体区域之后,我们就需要在窗体区域中添加我们需要自定义的控件了,这里的设计界面如下:

设计完界面之后,最后就是实现我们的后台逻辑了,即在后台写代码来完成我们所需要实现的功能。具体后台代码如下(因为代码注释中都有解释,大家不懂实现过程可以看代码注释):

  • // 对应的联系人(Contact)对象
  • private Outlook.ContactItem contactItem;
  • // 自定义属性对象
  • private Outlook.ItemProperty MotherName = null;
  • private Outlook.ItemProperty MotherTelNumber = null;
  • private Outlook.ItemProperty FatherName = null;
  • private Outlook.ItemProperty FatherTelNumber = null;
  • // 在显示窗体区域之前发生。
  • // 使用 this.OutlookItem 获取对当前 Outlook 项的引用。
  • // 使用 this.OutlookFormRegion 获取对窗体区域的引用。
  • private
    void ContactFormRegion_FormRegionShowing(object sender, System.EventArgs e)
  • {
  • // 获得FormRegion所对应的Contact对象
  • contactItem = this.OutlookItem as Outlook.ContactItem;
  • // 在从自定义属性中取出值时,首先确保自定义属性不为空。
  • EnsureProperties();
  • // 从联系人的自定义属性中取出值为控件赋值
  • txbMotherName.Text = MotherName.Value;
  • txbFatherName.Text = FatherName.Value;
  • txbMotherTel.Text = MotherTelNumber.Value;
  • txbFatherTel.Text = FatherTelNumber.Value;
  • }
  • // 在关闭窗体区域时发生。
  • // 使用 this.OutlookItem 获取对当前 Outlook 项的引用。
  • // 使用 this.OutlookFormRegion 获取对窗体区域的引用。
  • private
    void ContactFormRegion_FormRegionClosed(object sender, System.EventArgs e)
  • {
  • // 释放对象
  • System.Runtime.InteropServices.Marshal.FinalReleaseComObject(contactItem);
  • contactItem = null;
  • }
  • // 确保所有自定义属性不为空
  • private
    void EnsureProperties()
  • {
  • EnsureItemProperty(ref MotherName, "montherName", Outlook.OlUserPropertyType.olText);
  • EnsureItemProperty(ref FatherName, "fatherName", Outlook.OlUserPropertyType.olText);
  • EnsureItemProperty(ref MotherTelNumber, "motherTelNumber", Outlook.OlUserPropertyType.olText);
  • EnsureItemProperty(ref FatherTelNumber, "fatherTelNumber", Outlook.OlUserPropertyType.olText);
  • }
  • // 确保项目属性不为空引用
  • private
    void EnsureItemProperty(ref Outlook.ItemProperty property, string name, Outlook.OlUserPropertyType propertyType)
  • {
  • // 如果自定义属性为空时
  • // 首先从联系人项关联的属性集合中获得属性对象
  • // 如果项目集合中还不存在该属性时,就把该属性名称添加进ItemProperties集合中
  • if (property == null)
  • {
  • property = contactItem.ItemProperties[name];
  • if (property == null)
  • {
  • property = contactItem.ItemProperties.Add(name, propertyType);
  • }
  • }
  • }
  • // 父亲名字修改事件
  • private
    void txbFatherName_TextChanged(object sender, EventArgs e)
  • {
  • // 保存值到自定义的属性中
  • FatherName.Value = txbFatherName.Text;
  • }
  • // 父亲的电话号码修改事件
  • private
    void txbFatherTel_TextChanged(object sender, EventArgs e)
  • {
  • // 保存值到自定义的属性中
  • FatherTelNumber.Value = txbFatherTel.Text;
  • }
  • // 母亲名字修改事件
  • private
    void txbMotherName_TextChanged(object sender, EventArgs e)
  • {
  • // 保存值到自定义的属性中
  • MotherName.Value = txbMotherName.Text;
  • }
  • // 母亲的电话号码修改事件
  • private
    void txbMotherTel_TextChanged(object sender, EventArgs e)
  • {
  • // 保存值到自定义的属性中
  • MotherTelNumber.Value = txbMotherTel.Text;
  • }

从上面的代码中可以看出,主要的实现思路是——初始化联系人窗口,从自定义属性中获取值来初始化窗体中控件的值,如果自定义属性不存在时,此时就需要把自定义属性添加进ItemProperties集合中来确保自定义属性不为空,如果自定义属性存在,则直接中自定义属性中获取值来初始化窗体中的控件。最后注册窗体中每个控件的修改事件,把控件中值的修改保存到自定义属性中,这样以便下次打开联系人时可以获得修改过的数据
这样我们的设计就完成了,接下来看看程序的运行结果吧(按F5 运行该程序):
运行出现的第一个窗口为:

点击新建联系人之后,出现编辑联系人窗体,此时在窗体中可以看到我们自定义的窗体:

输入联系人的相关信息,点击保存并关闭按钮,然后我们再打开该联系人,修改"父亲电话"为 ”123456“(之前是123456789),点击保存并关闭按钮,当我们下次再打开该联系人时,此时可以获得修改后的数据信息:

这样就成功完成了我们开始所说的需求,当然这个还有很多不足的地方,比如没有对电话号码进行验证(如在电话号码文本框中输入中文或者不存在的号码,或者不是11位的号码等情况进行讨论)。

VSTO学习(六)——创建Outlook解决方案的更多相关文章

  1. VSTO之旅系列(五):创建Outlook解决方案

    原文:VSTO之旅系列(五):创建Outlook解决方案 本专题概要 引言 Outlook对象模型 自定义Outlook窗体 小结 一.引言 在上一个专题中,为大家简单介绍了下如何创建Word解决方案 ...

  2. VSTO学习笔记(一)VSTO概述

    原文:VSTO学习笔记(一)VSTO概述 接触VSTO纯属偶然,前段时间因为忙于一个项目,在客户端Excel中制作一个插件,从远程服务器端(SharePoint Excel Services)上下载E ...

  3. VSTO学习(五)——创建Word解决方案

    一.引言 在上一个专题中主要为大家介绍如何自定义我们的Excel 界面的,然而在这个专题中,我将为大家介绍如何用VSTO来创建Word项目,对于Word的VSTO开发和Excel的开发很类似,你同样也 ...

  4. VSTO之旅系列(二):创建Excel解决方案

    原文:VSTO之旅系列(二):创建Excel解决方案 本专题概要 引言 创建VSTO项目 Excel对象模型 创建Excel外接程序 创建Excel文档级自定义项 小结 一.引言 也许很多朋友都没有听 ...

  5. VSTO 学习笔记(六)在 Excel 2010中使用RDLC报表

    原文:VSTO 学习笔记(六)在 Excel 2010中使用RDLC报表 Excel具有强大的图表显示.分析功能,这点毋庸置疑,但是如果将常规MIS系统中的数据以报表的形式在Excel中显示,却并不那 ...

  6. VSTO之旅系列(四):创建Word解决方案

    原文:VSTO之旅系列(四):创建Word解决方案 本专题概要 引言 Word对象模型 创建Word外接程序 小结 一.引言 在上一个专题中主要为大家介绍如何自定义我们的Excel 界面的,然而在这个 ...

  7. VSTO学习笔记(二)Excel对象模型

    原文:VSTO学习笔记(二)Excel对象模型 上一次主要学习了VSTO的发展历史及其历代版本的新特性,概述了VSTO对开发人员的帮助和效率提升.从这次开始,将从VSTO 4.0开始,逐一探讨VSTO ...

  8. VSTO学习笔记(十四)Excel数据透视表与PowerPivot

    原文:VSTO学习笔记(十四)Excel数据透视表与PowerPivot 近期公司内部在做一种通用查询报表,方便人力资源分析.统计数据.由于之前公司系统中有一个类似的查询使用Excel数据透视表完成的 ...

  9. VSTO 学习笔记(十二)自定义公式与Ribbon

    原文:VSTO 学习笔记(十二)自定义公式与Ribbon 这几天工作中在开发一个Excel插件,包含自定义公式,根据条件从数据库中查询结果.这次我们来做一个简单的测试,达到类似的目的. 即在Excel ...

随机推荐

  1. 2018.08.17 bzoj4653: [Noi2016]区间(线段树+尺取法)

    传送门 将坐标离散化之后直接用尺取法(双指针)+线段树维护. 其实就是说只要目前所有点的被覆盖次数是大于等于m的就移动左指针删除区间更新答案,否则移动右指针加入区间更新答案. 话说忘记排序以及建树的时 ...

  2. Navicat for oracle cannot load OCI DLL

    Navicat for oracle 提示 cannot load OCI DLL87,126,193 instant client package is required for basic and ...

  3. HDU 3897 Base Station (网络流,最大闭合子图)

    题意:给定n个带权点m条无向带权边,选一个子图,则这个子图的权值为 边权和-点权和,求一个最大的权值. 析:把每条边都看成是一个新点,然后建图,就是一个裸的最大闭合子图. 代码如下: #pragma ...

  4. UVa 11210 Chinese Mahjong (暴力,递归寻找)

    题意:这个题意.有点麻烦,就是说给定13张牌,让你求能“听”的牌.(具体的见原题) 原题链接: https://uva.onlinejudge.org/index.php?option=com_onl ...

  5. HDU 2106 decimal system (进制转化求和)

    题意:给你n个r进制数,让你求和. 析:思路就是先转化成十进制,再加和. 代码如下: #include <iostream> #include <cstdio> #includ ...

  6. DDR的型号问题

    一.DDR的容量大小 先看下micron公司对DDR3命名的规则: 1.meg的含义: 内存中Meg的含义:Meg就是兆的含义,即1000,000. MT47H64M16 – 8 Meg x 16 x ...

  7. MFC框架仿真<三>R T T I

    RTTI,简单的说,就是判定A类是否为B类的基类.将书本的内容最大程度的简化,如下图的类层次,现在解决的问题就是:判定“梨”是否是“红富士”的基类.

  8. Android:手把手教你打造可缩放移动的ImageView(上)

    定义ImageView,实现功能如下: 1.初始化时图片垂直居中显示,拉伸图片宽度至ImageView宽度. 2.使用两根手指放大缩小图片,可设置最大放大倍数,当图片小于ImageView宽度时,在手 ...

  9. linux系统编程:setjmp和longjmp函数用法

    #include <stdio.h> #include <setjmp.h> //jmp_buf:数组,保存栈信息即运行环境 jmp_buf buf; double Divid ...

  10. 转载:R语言Data Frame数据框常用操作

    Data Frame一般被翻译为数据框,感觉就像是R中的表,由行和列组成,与Matrix不同的是,每个列可以是不同的数据类型,而Matrix是必须相同的. Data Frame每一列有列名,每一行也可 ...