本專題概要
- 引言
- 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窗體和我們的Outlook界面(自定義Outlook界面和自定義Excel界面很類似,具體操作可以參考專題三)。在下一個專題中將為大家介紹如何實現Office的自動化編程。
本專題源碼:http://files.cnblogs.com/zhili/VSTOOutlook.zip