My vsto path (5): contact extension for outlook preliminary development

Source: Internet
Author: User

In the previous lecture, we completed the introduction to word. At the beginning of the text, I will focus on outlook. Outlook is a very useful tool in Microsoft Office, especially in a corporate LAN with a Windows domain, outlook is the most commonly used communication tool for employees, therefore, there is a huge demand for further custom development of outlook. In this article, I first started with the extension of contacts to explain how to develop a powerful outlook plug-in.


The beginning of the story

First, let's assume a scenario. One day, colleagues from the marketing department came to you to help you (experienced people know that this is generally the beginning of endless pain ). They want to add their parents' birthday information to their outlook contact information to facilitate marketing (hey, how do you do marketing yourself ). At the same time, it is better to be consistent with the original contact interface of outlook for easy access. To meet your colleagues' expectations, you opened Visual Studio ......

After thinking about it, you have two functional points in your mind:

    1. Outlook form region: used to create an interface, which can be integrated with the original outlook interface.
    2. Contact user define fields: used to save newly added attributes.

The new contact interface is as follows:


Business logic: each time the contact interface is displayed, the form region we created will read the values in the User-Defined attributes in the contact (we create four user attributes for the parent's name and birthday respectively) and display them on the interface. When the contact is disabled, if the user changes the values of the four controls, we will write them back to the custom attributes. User-Defined attributes, such:


Outlook Object Model

Before getting started, let's take a look at the object model of outlook.

Microsoft. Office. InterOP. Outlook. Application

The Application Object in outlook is the top-level of all objects, just like the application object I have previously introduced in word. Even if you open multiple outlook at the same time, you only create one application (only one process ). In the Application object, we need to focus on three aspects:

    1. Createitem method: This method creates outlook objects, such as email, task, and contact.
    2. Schedulers attribute: obtains the current set of outlook. Explorer objects.
    3. Inspectors property: obtains the current set of outlook. Inspector objects.

There are many ways to obtain the application object. commonly used methods are obtained directly in The addin project through globals. thisaddin. application. If you have read the word plug-in that I have previously written, you will find that this is the same as word vsto. In fact, this is the pattern that Microsoft has set for us. This is also true for later Excel and PowerPoint versions. Here I will further introduce globals, which is a thisaddin. designer. A class defined in CS. For outlook, it defines three static attributes: thisaddin, ribbons, and inspectors objects. Globals is used to obtain the context we need anywhere in the addin project.


Microsoft. Office. InterOP. Outlook. Explorer

Explorer class, that is, the main window of the current outlook. Shows a window for displaying the folder content that contains items (such as email, task, or appointment. The Explorer class includes methods and properties that can be used to modify the window, and events that occur when the window is changed. Note that outlook supports multiple explorer, but only one application. This is similar to word, but it is different from Excel we will talk about later. Generally, we use the globals. thisaddin. application. activeexplorer () method to obtain the current (Focus) explorer.


Microsoft. Office. InterOP. Outlook. Inspector

Inspector class, that is, an outlook item window. For example, the window popped up when you write an email is an inspector, and a new contact you create is also an inspector. The Inspector Class is frequently used in the development of outlook plug-ins. In particular:

    1. Obtain the Current Inspector: globals. thisaddin. application. activeinspector (), we often use this method to obtain the Current Inspector, but this is not necessarily dependent. In today's example, we will talk about a special situation.
    2. Create a new inspector event: globals. thisaddin. application. Inspectors. newinspector. If you need to add a task pane for each email, you need to use this event.
    3. Obtain the outlook object corresponding to Inspector: Inspector. currentitem. Inspector is only a window, and the outlook object behind this window needs to be obtained through this method.


Microsoft. Office. InterOP. Outlook. mapifolder

Mapifolder is the directory in outlook. Outlook provides 16 built-in directory types, which are defined by enumeration of Microsoft. Office. InterOP. Outlook. oldefaultfolders.


Microsoft. Office. InterOP. Outlook. mailitem

Microsoft. Office. InterOP. Outlook. appointmentitem

Microsoft. Office. InterOP. Outlook. taskitem

Microsoft. Office. InterOP. Outlook. contactitem

They correspond to emails, meetingrequest, tasks, and contacts in Outlook respectively. They can be created through the createitem method of the Application object.


Outlook form Region


To make a better interface, we use Outlook form region. It started from Outlook 2007 and Microsoft entered a new technology. It provides a more convenient way to expand the Outlook project interface. Compared with the previous custom form, form region is based on. NET, which makes development easier and is more closely integrated with outlook.


Create form Region

First, add a new item and select outlook form region in the office project type.


We chose to design a new form region.


The form region type is adjoining, which is added at the bottom of the page.


If you need to add more controls on region form, you can also select separate, so that you will have a complete empty form. It becomes an independent tab and does not conflict with the original form.


Name form region and set to display our region form in both edit and read modes.


Our form region is embedded in the contact.


After completing these configurations, Vs will create an empty form region. If you need to modify the settings, you can modify them in the attributes, as shown in.


We start to add controls to this form. There are two textbox and two datetimepicker:


Business Logic implementation


This is based on our business logicCodeThe flowchart.


Source codeAnalysis

Member variables

1: // Custom attribute name
2: Private Const StringProperty_name_mother_name ="Property name mother name";
3: Private Const StringProperty_name_mother_birthday ="Property name mother Birthday";
4: Private Const StringProperty_name_father_name ="Property name father name";
5: Private Const StringProperty_name_father_birthday ="Property name Father Birthday";
7: // Custom property object
8: PrivateOutlook. userproperty _ mothernameproperty =Null;
9: PrivateOutlook. userproperty _ motherbirthdayproperty =Null;
10: PrivateOutlook. userproperty _ fathernameproperty =Null;
11: PrivateOutlook. userproperty _ fatherbirthdayproperty =Null;
13: // Corresponding contact object
14: PublicOutlook. contactitem _ contact =Null;
16: // Mark whether the content is modified
17: Private Bool_ Changed =False;


Formregionshowing event. Here we get the value from the User-Defined attribute of the contact and assign it to the control. If these attributes do not exist, we create them. At the same time, all our controls are bound with the changed event, so that we can determine whether the value is changed. Note that I need to obtain the contact object to read the property. However, if your form region is in adjoining mode, in the formregionshowing event, you will find that you use globals. thisaddin. application. activeinspector () cannot obtain inspector. Further, you cannot obtain currentitem through inspector. This issue is rarely mentioned in Microsoft forums. The method I used here is (employeefamilyform) sender). outlookitem. You can see the following code:

1: Private VoidEmployeefamilyform_formregionshowing (ObjectSender, system. eventargs E)
3: // Obtain the contact object corresponding to formregion
4:_ Contact = (employeefamilyform) sender). outlookitemAsOutlook. contactitem;
6: // Obtain the attributes of the mother's name from the custom attributes of the contact
7:_ Mothernameproperty = _ contact. userproperties. Find (property_name_mother_name, type. Missing );
8: If(_ Mothernameproperty! =Null)
10: // If this attribute exists, the value is taken out and assigned to the control.
11:Tbmothername. Text = _ mothernameproperty. ValueAsString;
13: Else
15: // This attribute is created if it does not exist.
16:_ Mothernameproperty = _ contact. userproperties. Add (property_name_mother_name, outlook. oluserpropertytype. oltext, type. Missing, type. Missing );
19: // Mother's birthday, same principle
20:_ Motherbirthdayproperty = _ contact. userproperties. Find (property_name_mother_birthday, type. Missing );
21: If(_ Motherbirthdayproperty! =Null)
23:Dtpmotherbirthday. value = (datetime) _ motherbirthdayproperty. value;
25: Else
27:_ Motherbirthdayproperty = _ contact. userproperties. Add (property_name_mother_birthday, outlook. oluserpropertytype. oldatetime, type. Missing, type. Missing );
30: // Father's name
31:_ Fathernameproperty = _ contact. userproperties. Find (property_name_father_name, type. Missing );
32: If(_ Fathernameproperty! =Null)
34:Tbfathername. Text = _ fathernameproperty. ValueAsString;
36: Else
38:_ Fathernameproperty = _ contact. userproperties. Add (property_name_father_name, outlook. oluserpropertytype. oltext, type. Missing, type. Missing );
41: // Father's birthday
42:_ Fatherbirthdayproperty = _ contact. userproperties. Find (property_name_father_birthday, type. Missing );
43: If(_ Fatherbirthdayproperty! =Null)
45:Dtpfatherbirthday. value = (datetime) _ fatherbirthdayproperty. value;
47: Else
49:_ Fatherbirthdayproperty = _ contact. userproperties. Add (property_name_father_birthday, outlook. oluserpropertytype. oldatetime, type. Missing, type. Missing );
52: // Bind the four controls to the change event. The value will be written back to the attribute corresponding to the contact only after modification.
53:Tbmothername. textchanged + =NewEventhandler (content_changed );
54:Dtpmotherbirthday. valuechanged + =NewEventhandler (content_changed );
55:Tbfathername. textchanged + =NewEventhandler (content_changed );
56:Dtpfatherbirthday. valuechanged + =NewEventhandler (content_changed );
58: // In the write event, save the modified value to the attribute
59:_ Contact. Write + =NewMicrosoft. Office. InterOP. Outlook. itemevents_10_writeeventhandler (contact_write );


Content_changed and contact_write events

1: VoidContent_changed (ObjectSender, eventargs E)
3: // When there is a modification, SET _ change to true
4:_ Changed =True;
7: VoidContact_write (Ref BoolCancel)
9: If(_ Changed)
11: // Save the value to the attribute
12:_ Mothernameproperty. value = tbmothername. Text. Trim ();
13:_ Motherbirthdayproperty. value = dtpmotherbirthday. value;
14:_ Fathernameproperty. value = tbfathername. Text. Trim ();
15:_ Fatherbirthdayproperty. value = dtpfatherbirthday. value;

Employeefamilyform_formregionclosed event

1: Private VoidEmployeefamilyform_formregionclosed (ObjectSender, system. eventargs E)
3: // Close event binding
4:_ Contact. Write-=NewMicrosoft. Office. InterOP. Outlook. itemevents_10_writeeventhandler (contact_write );
6: // Release the object
7:System. runtime. interopservices. Marshal. releasecomobject (_ contact );
8:_ Contact =Null;



Since then, we have completed the extension of outlook contacts. In this article, we have introduced the use of outlook form region and userproperties, and have successfully completed the requirements of the Marketing Department. After it helped them achieve this demand, colleagues from the marketing department came to them several days later. Because the number of customers is large, it is best to create a query tool to facilitate Content Retrieval. As for how to retrieve the outlook internal objects, and finally break them down.


Finally, this article is welcome to reprint, but please keep the source, if you have any questions, you can contact me or to vsto in the road group to ask questions. The source code involved in this article can be downloaded here.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.