Outlook: Programmatically select a custom Form Region

Tags: outlook, vsto

Hello, in this Article let me show you how to create a Custom Form Region, a Ribbon button and displaying this Form when you click on it.
For this demo we are extending the standard Outlook Contact Form.
First we need to create a VSTO Project – let's give it the Name "SwitchFormPage":

062909_2102_Howtoprogra1

Picture 1: Create a VSTO Outlook Add-in project

After you finished the project wizard you can add a custom Form Region to the project.
Just right-click the project and add a new Item. In the "Add New Item" dialog, select "Outlook Form Region".

062909_2102_Howtoprogra2

Picture 2: Adding a custom Form Region to the project

Let's give it the name "ContactInfo". In the following wizard, you can choose between two options:

A: Design a new form region – create it from scratch within Visual Studio using .Net Controls.
B: Import an Outlook Form Storage (.ofs) file. This means you can design a custom form region using the Outlook embedded form designer and save that as ".ofs" file, and import it here into visual Studio.

We create our form from scratch so let's choose A.

062909_2102_Howtoprogra3

Picture 3: Choose how you want to create your form region

Now you can select the type of the form you want to add. In this sample I want to demonstrate how to switch between forms and form regions, so we create a separate form region.
The Wizard is self-explanatory. On the Wizard select "Separate".

062909_2102_Howtoprogra4

Picture 4: Select the form region type

On the next screen you give the form region a descriptive text and select if the form region will be visible compose and/or in read mode.

062909_2102_Howtoprogra5

Picture 5: Description and display options

The next screen defines on what forms this form region will be visible.
You can choose between the standard forms, and define custom message classes where the form should appear.
I want the form region to show up on the default contact form so I select only "Contact (IPM.Contact)". "IPM.Contact" is the Outlook internal prefix used to identify a "ContactItem" – also called "MessageClass". Every Item in Outlook has a "MessageClass" property. In General there are different ways to check the type of an Item. You can use the Is Operator, the As Statement or check the "MessageClass" of an Item using late binding if the type is not enough – e.g. when you have custom message classes.
Why do I need this?
Since all Items are internally messages, you need a way to differentiate between the item types.
In many functions you will only get an object as Item type.
Let's have a look at the Application.Item_Send event. You can send out different Items (Emails, Meeting-Requests/Responses, Delivery-Reports, etc.).
Here is method A:

///<summary>
/// Eventhandler for the Item_Send event.
/// Is raised whenever an Item is sent out.
///</summary>
///<param name="Item">The Item that is sent.</param>
///<param name="Cancel">Set Cancel to true to interrupt the send process for the Item</param>
void Application_ItemSend(object Item, ref bool Cancel) {
 
    if (Item is Outlook.MailItem) {
        // Email
        // Cast to EmailItem
        Outlook.MailItem mail = (Outlook.MailItem)Item;
        // ...
 
    } else if (Item is Outlook.MeetingItem) {
 
        // Meting
        // Cast to MeetingItem
        Outlook.MeetingItem mail = (Outlook.MeetingItem)Item;
 
        // ....
 
    }
}

Listing 1: Using the is operator to determine the Item type.

///<summary>
/// Eventhandler for the Item_Send event.
/// Is raised whenever an Item is sent out.
///</summary>
///<param name="Item">The Item that is sent.</param>
///<param name="Cancel">Set Cancel to true to interrupt the send process for the Item</param>
void Application_ItemSend(object Item, ref bool Cancel) {
 
    // best, when you only test fo a single type
    Outlook.MailItem mail = Item as Outlook.MailItem;
 
    if (mail != null) {
        // we got it
        // ...
    }
}

Listing 2: Use the as Operator if you only want to test for a single type.

///<summary>
/// Eventhandler for the Item_Send event.
/// Is raised whenever an Item is sent out.
///</summary>
///<param name="Item">The Item that is sent.</param>
///<param name="Cancel">Set Cancel to true to interrupt the send process for the Item</param>
void Application_ItemSend(object Item, ref bool Cancel) {
 
    // Read the MessageClass property of the Item using late binding
    string messageClass = (string)Item.GetType().InvokeMember("MessageClass", BindingFlags.GetProperty, null, Item, null);
    switch (messageClass) {
        case "IPM.Post":
            Outlook.MailItem mail = (Outlook.MailItem)Item;
            // ... do something
            break;
 
        case "IPM.Post.CustomMessageClass":
            Outlook.MailItem customMail = (Outlook.MailItem)Item;
            // ... do something other stuff
            break;
 
    }
} 

Listing 3: Reading the MessageClass property using late binding

Choose the best option depending on your use case. A small excursion about message classes. But now back to the form page.
When you finished the form page wizard, you fill find a new user control in your project that represents the custom form region.
You can design it as you like using the Visual Studio Designer. Just double-click it and add some controls on it.
In my case I added a Splitter, a ListView on Panle1 and a WebBrowser on Panel2.

062909_2102_Howtoprogra6

Picture 6: Design a form region like a user control in visual studio

When you designed your Form, you can start debugging by pressing "F5" and when you create a new or open an existing contact,
you may notice that your custom form region appears as extra Item within the Ribbon.
When you click on the "Contact Information" entry, you will see your form region in the contact form.

062909_2102_Howtoprogra7

Picture 7: The custom form region is visible after you clicked the menu entry.

Next, we want to extend the Ribbon and create a custom button that displays our form region when clicked. Again we need to add a new Item to the project.
In the "Add New Item" dialog select "Ribbon (Visual Designer)". I called it "ContactFormRibbon".

062909_2102_Howtoprogra8

Picture 8: Adding a Ribbon to the project

The Ribbon has Special Menus, Tabs, Groups and Controls. I want to have an extra group called "X4U" with a king size button on it. On the contact form normally you have three tabs: "Contact", "Insert" and "Format Text".
I want to display my group on the left outer side of the "Contact" tab.

First set the Item type, where the Ribbon should be modified. You can do it by clicking on the Ribbon itself.

062909_2102_Howtoprogra9

Picture 9: Click on the Ribbon container and choose the Item types to be modified

Then click at the Tab and change the settings as you can see on the next screen.
Change "Label" to "Contact", "Name" to "TabContact", "ControlIdType" to "Office" and "OfficeId" to "TabContact".

062909_2102_Howtoprogra10

Picture 10: Modify the ControlId settings of the tab container.

You may ask: Where do I know the Office Id's ?
Answer: You can download it from Microsoft as Excel file. It's called Office Ribbon Ids.

http://www.microsoft.com/downloads/details.aspx?familyid=4329D9E9-4D11-46A5-898D-23E4F331E9AE&displaylang=en

Next we modify the group so that it shows up before the group named "Actions".
The important things here are "PositionType" it should be altered to "BeforeOfficeId" and "OfficeId" – it must be changed to "GroupActions".

062909_2102_Howtoprogra11

Picture 11: Settings for the group container

The properties of the button I added to the Ribbon using the designer are not so important. You can give him a name and when you double-click the button, an event-handler stub is generated in the code behind file for the Ribbon.
And here is the most important part that demonstrated how to display a specific page when you click the button.

private void buttonShowInfo_Click(object sender, RibbonControlEventArgs e) {
    // Access the current Inspector Object
    Outlook.Inspector inspector = this.Context as Outlook.Inspector;
 
    // Set the Custom Form Region as current page
    // Important: use the full qualified name of the class here
    // namespace.classname
    inspector.SetCurrentFormPage("SwitchFormPage.ContactInfo");
 
    // release inspector objects immediatly
    inspector = null;
} 

Listing 4: The button click event handler

Important is the name you are using. It must be the full class name of the custom form region. In my case the form region is named "ContactInfo" and the namespace is "SwitchFormPage".
Just press "F5" to debug and it works as expected.

062909_2102_Howtoprogra12

Picture 12: The new Ribbon button in the left corner

After clicking the button you will see your custom form page.

062909_2102_Howtoprogra13

Picture 13: Click on the button changes the current form page

I hope that will help you VSTO guys out there.
--[ Helmut ]--

Add a Comment