Share via


Chapter 13: Creating Form Regions

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

This article is an excerpt from Programming Applications for Microsoft Office Outlook 2007 by Randy Byrne and Ryan Gregg, from Microsoft Press (ISBN 9780735622494, copyright Microsoft Press 2007, all rights reserved). No part of these chapters may be reproduced, stored in a retrieval system, or transmitted in any form or by any means—electronic, electrostatic, mechanical, photocopying, recording, or otherwise—without the prior written permission of the publisher, except in the case of brief quotations embodied in critical articles or reviews.

In this chapter, you'll find a high-level introduction to the form region design experience and then a deep dive into creating a custom form solution using form regions in Microsoft Office Outlook 2007. Form regions provide a custom user interface mechanism that allows you to extend built-in forms in multiple ways or completely replace a built-in form with your own custom interface. Through this deep dive, we'll cover the following:

  • Form region scenarios

  • Designing a form region with Outlook

  • Programming a form region from an add-in

To facilitate our discussion, most of the scenarios and concepts explained in this chapter revolve around the travel agency sample code available on the book's companion Web site. However, the detail level will be sufficient that you will not need the sample code to understand the concepts explained in this chapter.

Contents

  • Introduction to Form Regions

  • Becoming Familiar with Form Region Design

  • Form Region End to End

  • Summary

  • Additional Resources

Introduction to Form Regions

This section provides a high-level overview of Outlook form region components and the differences between form regions and custom forms using form pages. For the purposes of this chapter, we use the following terminology:

  • **Custom forms with form pages   **This refers to custom forms and their associated user interface (UI) pages designed in the Outlook Forms Designer in Microsoft Outlook 97 through Outlook 2007 that can be published to a forms library such as the Organizational or Personal Forms Library, a Folder Forms Library, or embedded as a one-off form.

  • Custom forms with form regions   This refers to custom or built-in forms and their associated UI regions designed in the Outlook 2007 Forms Designer and saved as .ofs files. A custom form with form regions is made up of individual form regions registered on the same message class.

  • Custom forms   This refers to a collection of form pages or form regions that make up one whole form. Each item in Outlook has either a standard or custom form associated with it that Outlook will use to render the display of that item in the Inspector, the Reading Pane, or both.

Form Pages Compared with Form Regions

Outlook 2007 provides two different technologies for developing form solutions with Outlook. Both of these customization techniques use the same Outlook Forms Designer, but form regions provide many options and abilities that are lacking with form pages. Custom forms with form pages that are designed for earlier versions of Outlook will continue to work; however, the new Office Fluent Ribbon command UI might change the way custom command bars and controls appear on these custom forms. For new solutions that support Outlook 2007 and future versions, custom forms with form regions are the preferred way to customize Outlook forms. Table 13-1 provides a summary of the top features provided by custom forms and form regions.

Table 13-1. Comparing custom forms and form regions

Feature/Area

Custom forms with form pages

Custom forms with form regions

Supported Outlook versions

Outlook 97 through Outlook 2007.

Outlook 2007

Visual appearance

No support for Windows theming; forms look like Microsoft Windows 95.

Full support for Windows themes; forms match Outlook visuals.

Form layout

Designed using Outlook Forms Designer.

Designed using Outlook Forms Designer.

Supported controls

Standard form controls, ActiveX controls.

Enhanced form controls, Outlook controls, ActiveX controls.

Reading Pane

Standard form is always displayed; if there is script behind the form, Reading Pane display is disabled.

Adjoining and replacement form regions can be displayed.

Business logic

Written in Microsoft Visual Basic Scripting Edition (VBScript) using Outlook script editor.

Written as Component Object Model (COM) add-in in any language.

Deployment

Published to a forms library.

Distributed with an add-in.

Localization

Separate form version required for each localized language; difficult to maintain and deploy.

Integrated solution for localizing form text and optional layout changes.

Form Region Types

Form regions can be displayed in four different styles, based on the needs of a solution. Each type of form region is designed using the same experience and the same process with the Outlook Forms Designer. The manifest file that defines a form region determines the way Outlook displays the form region.

Adjoining Form Regions

Adjoining form regions are an additive option for an existing standard form or custom form. Adjoining form regions, as shown in Figure 13-1, are displayed in a special region at the bottom of the Inspector, the Reading Pane, or both, and are shown with a header that enables the region to be expanded and collapsed. Adjoining form regions enable developers to add more fields or related information to the first form page without customizing the entire form body.

Figure 13-1. An example of an adjoining form region on a mail item

Adjoining form region on a mail item

Separate Form Regions

Separate form regions are another additive option for standard forms or custom forms. Separate form regions are displayed as a new form page on a preexisting form (either custom or standard), as shown in Figure 13-2. The additional form page appears to be part of the form and can be selected using an additional button in the Show group on the Office Fluent Ribbon. Several separate form region pages can be added to a replacement or replace-all form region to build a multipage form.

Figure 13-2. An example of a separate form region on a task item

Separate form region on a task item

Replacement and Replace-All Form Regions

Replacement and replace-all form regions are a special type of separate form region that causes default form pages to be removed from an item. A replacement form region will delete the first page of the form pages and replace it with the form region (see Figure 13-3). A replace-all form region will delete all the form pages and display only the replace-all form region and other form regions registered with the item's message class. To build up a multipage custom form with form regions, you combine a replace-all form region with several separate form regions.

Figure 13-3. An example of a replacement form region on an appointment item

Replacement form region on an appointment item

Standard Form Types

In addition to the types of form regions, there are also several types of forms in Outlook. Each built-in form type describes one of the standard item types in Outlook. The built-in forms include Message, Post, Task, Appointment, Journal, and Contacts. Using form regions, any part of these built-in forms can be replaced and customized, so you should use the base form type that most closely matches the type of item your form region solution provides. When creating a new form region, the designer does not provide a base template for that particular item type.

Selecting the right base form can make it easier for you to design your form because the Field Chooser will display a list of the most commonly used fields for that item type. However, just because you started to design a form on a contact item, for example, does not mean that form will not function on other item types. As long as the fields used on the form are defined on the item, your form region can be displayed on any item type.

Anatomy of a Form Region Solution

A solution built around form regions includes the following elements:

  • **Form region manifest   **This file is an Extensible Markup Language (XML) file that provides details that define the form region, including how the form region is loaded, what type of form region, and the display text for the form region and the controls. See the section "Authoring a Form Region Manifest" later in this chapter for details on this manifest format.

  • **Form storage file   **The storage file is a binary file that describes the layout of the form. This file can be created and edited using the Outlook Forms Designer.

  • **Registry entries   **Each form region needs one or more registry entries that point to the form region manifest. Each registry entry defines one message class that will use the form region. See the section "Registering a Form Region" later in this chapter for more details.

  • **COM add-in (optional)   **If a form region needs business logic or other custom code running with the form region, that logic is implemented in a COM add-in. The form region manifest file indicates the ProgID or name of the add-in that will be called when the form region is loaded. An add-in can also be used to supply Office Fluent Ribbon customizations for form region items.

Becoming Familiar with Form Region Design

This section covers the components of forms in Design mode and discusses the parts of an Outlook form region.

How Is a Form Opened?

Because of security work that went into Microsoft Office Outlook 2003 and Outlook 2007, Outlook no longer supports, by default, loading a form definition from an item. This question then arises: If the form definition doesn't travel with the item, how is the form opened? The answer is that the form is launched by looking for a form that matches the message class on the item in a few different locations. Each item includes a property that indicates the message class of the form that was used to compose the item, such as IPM.Contact. This message class provides an identifier that Outlook compares against the identifier on a form or form region to determine whether the form should be displayed.

When Outlook starts to look for a form with the matching message class, it first checks to see if any form regions are registered for the message class of the item. If a form region is registered and is a replacement or replace-all form region, Outlook stops the search and loads the form regions. If no form region is registered or the form regions are adjoining or separate form regions, Outlook continues to look for a form to load.

If no form region is loaded, Outlook then looks to see whether a custom form is published in the same folder as the item. If no form is found in the folder, Outlook then looks to the Personal Forms Library and then the Organizational Forms Library to see whether a form is available in that library.

If no form is located using the exact message class on the item, Outlook repeats the check for the next class in common. For example, if IPM.Note.Myform.ThisForm does not exist, Outlook tries to open IPM.Note.Myform. If that form definition does not exist, IPM.Note loads and the user sees a standard message form. A form region can override this behavior using a special value in the manifest file that tells Outlook that only items that match the message class exactly should show the form region.

Designing a Form Region

Designing a new form region is very similar to working with a custom form. You can use the same designer interface that Outlook provides for developing custom forms, although the behavior of form regions is more advanced than custom forms. This section describes how to access the Outlook Forms Designer, describes the implications of Design mode, and walks you through creating a new form region.

Outlook Form Design Mode

The following elements (shown in Figure 13-4) are available when an Outlook form is in Design mode:

  • **Forms Designer window   **This shows the various pages of the form and the form properties and actions.

  • **Toolbox   **This allows you to add new controls (such as buttons) to the form.

  • **Field Chooser   **This allows you to select fields for the form.

  • **Properties dialog box   **This allows you to modify a control or field.

  • **Advanced Properties   **This is used to modify an advanced property of the form or control.

Figure 13-4. These elements are available when Outlook forms are in Design mode

Elements available when forms are in Design mode

Entering Design Mode

To design a form region, you must start with a custom form. To enter Design mode for a custom form, follow these steps:

  1. In the Outlook Explorer window, select the Tools menu, point to Forms, and click Design A Form.

  2. Select the base form type that matches the type of form region you will be designing, and click Open. For this example, select Contact.

Outlook then opens a Contact custom form in Design mode. This form is a custom form that contains form pages but does not yet contain a form region. To add a new form region to the Outlook Forms Designer, on the Developer tab, in the Design group, click Form Region, and then click New Form Region. A new tab with the name "(Form Region)" will appear with an empty design surface. This is where you can design the layout of your new form region. Once a form region is open in Design mode, you can adjust the layout of controls, add or remove controls, and adjust the properties of controls on the form.

Important noteImportant

Form regions should only be designed using the standard DPI resolution in Windows (96 dpi). Form regions include a feature to automatically scale a form region to the appropriate resolution, but this feature only works one way. Designing your form at a high DPI setting will cause unexpected behavior when the form is displayed or opened again in the designer.

Renaming a Form Region Tab

To make it easier to keep track of multiple open form regions, you can rename the text that is displayed in the tab strip in the Outlook Forms Designer. To rename the form region page, click the Developer tab. In the Design group, click Page, and then select Rename Page.

The value entered for the page name is only used in the Forms Designer. To rename the text used to represent a separate, replacement, or replace-all form region in the Show group of the Office Fluent Ribbon when the form is running, you need to specify the <formRegionName> element in the form region manifest, which is described later in this chapter.

Saving a Form Region

To save a form region as an Outlook Form Storage (OFS) file, click the Developer tab. In the Design group, click Form Region, and then click Save Form Region As. This displays a Save File dialog box that will let you select the path to save the form region. Form regions can only be saved as .ofs files.

Important noteImportant

Do not use the Microsoft Office menu Save command to save a form region. This will save the form as an item in an Outlook folder. Also, do not use the Microsoft Office menu Save As command to save a form as an .msg or .oft file. Neither of these methods persist the form region information. The form region must always be saved separately.

Adding Controls

Controls can be added to a form region in two different ways: using the Control Toolbox or using the Field Chooser. These two methods for adding controls are explained in the following sections.

The Control Toolbox

The Control Toolbox window displays the available controls that can be added to the form. To access the Control Toolbox, on the Developer tab, in the Tools group, click Control Toolbox. By default, this toolbox displays only the Microsoft Forms 2.0 controls that are available for use on custom forms and form regions. For more information on adding the new controls discussed in Chapter 14, "Form Region Controls," see the next section, "Adding Additional Controls to the Control Toolbox." Custom ActiveX controls can also be added to the Control Toolbox and dropped onto a custom form or form region.

To add a control from the Control Toolbox to the form, click that control's icon in the Control Toolbox, and then click the location where the control should be created. If you click the control and then drag it to the form, the control will use a nondefault size. The recommended practice for adding controls to a form region is to use the click and click method rather than click and drag.

Adding Additional Controls to the Control Toolbox

To add additional ActiveX controls, such as the Outlook 2007 form controls, to the Control Toolbox, follow these steps:

  1. Right-click the Controls tab of the Control Toolbox, and select Custom Controls. The Additional Controls window opens, showing all the available controls.

  2. Select the check box next to the ActiveX controls you want to display on the Control Toolbox. Display names for Outlook 2007 form controls begin with "Microsoft Office Outlook."

  3. Click OK to return to the Forms Designer.

Figure 13-5 shows an example of the Control Toolbox and Additional Controls dialog box with the Outlook 2007 form controls selected.

Figure 13-5. Control Toolbox and Additional Controls dialog box with the Outlook 2007 form controls selected

Control Toolbox and Additional Controls dialog box

Creating a Control Template

To increase your productivity during the form design phase, you can create a control template by using the selection tool to select a group of controls and then dragging the selection back to the Control Toolbox. Follow these steps to create a control template:

  1. Select the controls you wish to use in the template with the selection tool.

  2. Drag the selection to the Control Toolbox.

  3. Outlook uses the default label New Group for the control template. If you want to rename the control template, right-click the template in the Control Toolbox, and then select Customize New Group.

  4. Enter the correct template name in the Customize Control dialog box in the ToolTip Text edit box. For example, you might create a label and edit box template (see Figure 13-6) and use Label/Edit Controls for the ToolTip text.

  5. Click OK to accept the new ToolTip text for the control template.

When you use a control template, you can either click the control template and drag it from the Control Toolbox to your form, or you can select the control template in the Control Toolbox and then click on the form design surface to insert a copy of the control template.

Figure 13-6. Creating a control template that contains a label and edit box

Control template containing a label and edit box

Accessing Control Properties

After a control has been added to the custom form or form region, you can set the properties of the control. Control properties determine what the control looks like and how it behaves when the control is running on the form.

Each control added to a form region has the same set of basic properties, which can be set using the Properties window (see Figure 13-7). To open the Properties window, select a control on the form. On the Office Fluent Ribbon Developer tab, in the Tools group, click Property Sheet. If no control is selected, this button will be disabled.

Figure 13-7. Properties window with the Display tab selected

Properties window with the Display tab selected

The Properties window has three or four tabs, depending on the type of control selected. If the control supports Outlook data binding, you will see four tabs: Display, Layout, Value, and Validation. If the control does not support Outlook data binding, you will see only three tabs: Display, Layout, and Validation.

The Display tab of the Properties window displays basic properties that adjust the look of the control. On this tab, you can set the name of the control, caption, font, foreground and background color, and whether the control is visible, enabled, read-only, sunken, or multiline. Note that not all of these options are available on every control.

The Layout tab of the Properties window displays properties that adjust how the control is positioned on the form. On this tab, you can adjust the top value, left value, height, and width of the control, and set properties on how the control is automatically positioned on the form. For more information on the automatic layout functionality of form regions, see the section "Understanding Automatic Layout" later in this chapter.

The Value tab of the Properties window displays properties that enable data binding between Outlook properties and the control. On this tab, you select a field from the Outlook item that will be data bound to a property of the control. If you use the Field Chooser to create new controls (see the section "Using the Field Chooser" later in this chapter), this information is automatically populated according to the field you selected.

The Validation tab of the Properties window provides options for basic data validation on some controls. Validation is available only if the control supports data validation, and the control is bound to an Outlook field on the Value tab. If the control does not support data binding or is not bound to a field, the controls on this tab are disabled.

Control Advanced Properties

Beyond the properties exposed through the Properties window, you can access more properties of a control, including properties that are specific to the selected control, by using the Advanced Properties dialog box.

To display the Advanced Properties dialog box, on the Office Fluent Ribbon, on the Developer tab, in the Tools group, click Advanced Properties. This displays the Advanced Properties dialog box for the current control, as shown in Figure 13-8. Unlike the Properties window, the Advanced Properties dialog box can stay open and automatically adjusts the list of properties for the currently selected control. If no control is selected, the properties for the form container are displayed.

Figure 13-8. Advanced Properties dialog box for the Outlook Time Control

Advanced Properties dialog box for Time control

Working with Fields

Nearly every form region solution will want to display some information that is stored on the item the form region represents. The best way to accomplish this result is to use the Outlook data binding mechanism to bind the field (also known as an item property or user property) to the control. You can accomplish this data binding by using the Field Chooser, by using the Value tab of the Properties window, or via business logic (code). When a control is data bound, the value of the field is automatically loaded into the control when the form region is opened. The value is also automatically saved back into the field if the control is changed while the form region is open.

Using the Field Chooser

The Field Chooser is the easiest way to add a bound field to a form region. To open the Field Chooser window, on the Office Fluent Ribbon, on the Developer tab, in the Tools group, click Field Chooser. This displays the Field Chooser window shown in Figure 13-9. The Field Chooser window has two components: a drop-down control that shows the field groups, and a list of fields. There are also two buttons at the bottom of the window used to create or remove custom fields.

Figure 13-9. The default Field Chooser appearance for a Contact form

Default Field Chooser appearance for Contact form

To create a new control on the form data bound to a field, drag the name of the field to the form design surface. This action automatically creates a label and control for the field. Depending on the field type, the control will be either a text box, combo box, or other standard control. Dragging a control from the Field Chooser window will not create any of the new Outlook-specific controls, like the Outlook Category Control or the Outlook Business Card Control. To use these controls on your form, you must explicitly add them to the form using the Control Toolbox as explained earlier in this chapter.

Binding Data with a Control

Instead of dragging a field from the Field Chooser to the form and allowing Outlook to automatically configure the data binding properties, you can data bind a control already on the form. If you are using a custom ActiveX control, you need to use this approach because the Field Chooser will not create a new custom ActiveX control for a field.

To adjust the data binding properties, click a control and then on the Office Fluent Ribbon, on the Developer tab, in the Tools group, click the Property Sheet button. After the Properties window opens, click the Value tab to view the data binding properties. Figure 13-10 illustrates what these settings look like.

Figure 13-10. Data binding properties for a control in the Properties window

Data binding properties for a control

To select the field with which the control will data bind, click Choose Field, and select a new field using the menu that appears. The Type and Format values will automatically be updated to the default for the type of field selected. For some field types, the Format property can be changed to adjust the formatting used when displaying the contents of the property.

You can also use the Property To Use drop-down list to determine which property will be set with the value of the field. If you are using a custom ActiveX control, you can assign the value to a different property than the default Value property. For example, if you want the field data to go into the Text property of the control, you can set Property To Use to be Text.

Creating Custom Fields

In addition to using the standard fields on the item, you can create custom fields known as user properties. There are two ways to create custom fields, and the method of creating the field determines how the field will roam with the form.

If you create a new user property using the Field Chooser, the field will be created in the default folder for the type of form being designed. Fields that have the field definition stored in the folder must be re-created in each folder when an item is copied into that folder for the field to work properly and be available in the Folder Contents view. You will need to use an add-in to make sure the field is properly created before opening an instance of the form in a folder for the first time. See UserDefinedProperties in Chapter 6, "Accessing Outlook Data," for more information on creating a user property in a folder.

If you create a new user property using the Value tab of the Properties window, the field definition will be stored in the form region file and will automatically be available on any item after the form region has been loaded. In this case, you do not need to write an add-in to create the user property in a folder each time an item is opened from a new folder. However, user properties that are defined in the form region cannot be added to the view or used in a search filter for the Restrict method of the Items collection or the Table object. Table 13-2 illustrates how custom property creation for a form region determines the availability of the custom property in a folder.

Table 13-2. Creating a user property in a form region

Description

Custom property available in folder

Custom property available in View

Custom property available for Table.Restrict or Items.Restrict

Created on Value tab of Control Properties window by clicking New

Always

Not available

Not available

Created in Field Chooser by clicking New

Must use add-in code to create UserDefinedProperty in any folder that contains the item

Available

Available

Polishing Your Form Region

Once you have completed the initial design of a form region, you should take some time to polish the design of the form region to make sure that it fits with the standard Outlook look and feel. Form regions support an advanced automatic layout system that will allow your form to grow and shrink as the user resizes the window. Taking advantage of this system requires understanding how it works and ensuring that your form is designed within the guidelines of the system. If you choose not to use the automatic layout, you can control the layout of the form manually by writing your own resizing code or using a third-party control.

Understanding Automatic Layout

Form regions provide a layout ability that works different from the Resize With Form option that is available on custom form pages. The system used by form regions works similar to what the Outlook built-in forms use to automatically adjust the size of the form to fit the window as it is resized.

The form layout is calculated by fitting a table over the form design, where there is one control per table cell. Each row and column of this layout table will pick up certain margins that keep the controls spaced out as they were initially designed. When the user resizes the window displaying a form region, this table is stretched to fit the new window, and the controls in each cell of the table are adjusted as appropriate. This method is designed to help keep controls aligned in their individual columns on the form so that a control's label and the control itself maintain alignment relative to other controls on the form.

However, there are some limitations to this method, including these:

  • Controls cannot overlap or intersect. Controls that do overlap or intersect will be ignored when the layout is calculated.

  • Some controls might "snap" into their place and not stay exactly where they were positioned on the form.

To adjust the way controls are positioned on the form, there are several options on the Layout tab of the Properties window for any control placed on a form region. Figure 13-11 shows an example of these settings. There are five settings that pertain to the layout of the control on the form:

  • **Enable Automatic Layout For This Control   **This check box determines whether this control is included in the automatic layout scheme or not. If this check box is cleared, the control will not be automatically positioned on the form.

  • **Horizontal   **The value chosen in this drop-down list box determines how the control is aligned in the layout cell horizontally. If the value is Grow/Shrink With Form, then the control will automatically grow or shrink to fit the available space. Otherwise the control will align according to the selected value.

  • **Minimum Width   **The value in this text box sets the smallest width to which the control will automatically resize. This allows you to keep a control at a particular minimum size, even as the form shrinks further.

  • **Vertical   **The setting in this drop-down list box determines how the control is aligned in the layout cell vertically. If the value is set to Grow/Shrink With Form, then the control will automatically expand or collapse vertically to fit the available space. Other values will keep the control aligned vertically without causing the control to resize.

  • **Minimum Height   **The value in this text box sets the smallest height to which the control will automatically resize. This allows you to keep a control at a particular minimum height, even as the form shrinks smaller.

Figure 13-11. Options on the Layout tab of the Properties window for a control

Layout tab of the Properties window for a control

Layout Guidelines

Designing your form region solution to work in a way similar to the built-in features in Outlook will make it easier for your users to understand your solution because it will work in a manner with which they are already familiar. As part of designing a form region, you should attempt to follow some of the form design guidelines used by the standard Outlook forms, including the following:

  • Keep four pixels of padding between the edge of the form and any control.

  • Remember to add the Infobar and Category controls to a replacement or replace-all form region. These controls show important information that might not be displayed in any other way to the user. These controls should be arranged at the top of the form, with the Infobar control above the Category control.

  • Use a one- or two-column layout to keep the controls organized.

  • Allow fields that might contain a large amount of text to resize with the form. Fields that contain a small amount of text or a fixed length should not resize.

  • Configure the body/notes field to resize both vertically and horizontally.

  • Use additional form pages for less prominent controls.

  • Use the Office Fluent Ribbon instead of a command button for actions that are not associated with any particular control on the form.

Fixing Layout Errors

Sometimes when a form region uses automatic layout, it might not appear as the designer expected. This is usually due to a problem with the way the form was designed, violating a limitation of the automatic layout logic. A special command exists to detect any controls that might be in a conflict state so that the form developer can adjust the controls as necessary.

To find controls that are in an error state and will not be properly adjusted by the automatic layout logic, on the Office Fluent Ribbon, on the Developer tab, in the Arrange group, click the Region Layout button, and then click Select Controls With Layout Errors. This command selects any controls that are in conflict. Figure 13-12 shows the Region Layout menu expanded. If no controls are selected after clicking this command, everything should lay out properly. This same menu also includes two other options, Recalculate Layout and Resize Layout With Form Designer. These commands can be used to test how the layout will work when the form is run by enabling automatic layout to be used in the designer. However, as a general rule, designing a form with automatic layout enabled might not work as expected and should be avoided.

Figure 13-12. Commands in the Arrange group of the Developer tab that can help diagnose layout problems with a form region

Commands in the Arrange group of the Developer tab

Form Region Theme Support

To make it easier for a form region solution to look like it is a part of Outlook, form regions automatically support the Outlook visual theme. All of the new Outlook form controls support the Windows themed appearance by default. There are also new Outlook form controls that provide UI elements unique to Outlook 2007, such as the Business Card preview, new colored category strip, and the Contact Photo Control. These controls can be used to ensure a visual similarity between a form region and Outlook built-in forms.

Additionally, special values for some properties of the controls will be automatically adjusted to display using the Outlook colors selected by the user. Table 13-3 explains which properties and values can be used in this way.

Table 13-3. Theme-supporting properties and values

Control

Property

Values/Description

All Olk* controls, form region

BackColor

Button face is automatically adjusted to be the appropriate background color for the form (usually white in the Reading Pane, blue in the Inspector, and black in high-contrast mode).

All Olk* controls, form region

ForeColor

Button Text is used to represent the standard text color on the form (usually black in the Reading Pane and Inspector and white in high-contrast mode).

OlkLabel

UseHeaderColor

True: The label will use the font color that represents header values (usually blue in the Reading Pane and black in the Inspector window).

Making a Form Region Sendable

In some cases, you might want to make a custom form with form regions that can be sent via e-mail to other recipients. In particular, if you wanted to customize the message or appointment forms in a particular way for a custom form type, you would still want to make sure someone could send one of these messages in a way with which he or she is familiar.

With Outlook 2007, the Send button has moved onto the form page itself instead of being in a toolbar or the Office Fluent Ribbon. To re-create this functionality in a form region, you need to add a command button that provides the same capability. To add a Send button to your form region, follow these steps:

  1. Open the Field Chooser window.

  2. From the drop-down list of field collections, select All Mail Fields.

  3. Find the Submit field in the list, and drag it to your form region. A new button will be created with the label Submit.

You can also add a picture to the Send button by setting the Picture and PictureAlignment properties on the button. The large Send button on e-mail messages and appointment forms shows an envelope icon centered and aligned above the text.

You should also add the Accounts button for users who have more than one account and need to select which account should be used to send the message. To add the Accounts button, follow these steps:

  1. Open the Field Chooser.

  2. From the drop-down list of field collections, select All Mail Fields.

  3. Find the Accounts field in the list, and drag it to the form region.

  4. Click the newly created Accounts button, and open the Advanced Properties dialog box for the control.

  5. Set the DisplayDropArrow property to True.

If your solution is running with an add-in behind the form that contains business logic, you might want to hide the Accounts button if only one account is defined in the Outlook profile. To determine the number of accounts available, you can use the NameSpace.Accounts.Count property and adjust the visibility of the button accordingly.

Differences Between Custom Forms with Form Regions and Custom Forms with Form Pages

For Outlook custom forms with form pages, Outlook automatically adds Send and Accounts buttons to the default built-in Office Fluent Ribbon tab for the item type to allow legacy forms that relied on Microsoft Office Outlook 2003 behavior to continue to work. These buttons will always be enabled and visible, even if VBScript for the custom form disables the Send button on the legacy command bars. Form designers who want to disable the Send button on custom forms in Outlook 2007 need to use Office Fluent Ribbon extensibility or convert the forms to form regions to maintain this behavior.

Form Region End to End

Now that you've read more about the concepts around form regions and the form region designer, you can move into creating a form region solution. In this example, you will see how to build all the important pieces of an end-to-end form region solution, including creating a form region, hooking that form region up to an add-in, registering the form region, and deploying the solution.

All of the code mentioned in this section is available in the Travel Agency sample on this book's companion Web site. The scenario covered here is an extension to the standard Contact form in Outlook that will provide a new form page with specific client fields, like frequent flyer number, and a list of purchased itineraries.

Step 1: Creating a Form Region

Before you get started writing an add-in behind the form or otherwise working on business logic and deployment, you need to have a form region design. To complete this step, use the Outlook Forms Designer, and create the .ofs file that contains the layout information. Figure 13-13 shows the form region you are creating.

Figure 13-13. Separate form region for a Contact item from the Travel Agency sample

Separate form region for a Contact item

To design this form, follow these steps:

  1. Start Outlook 2007.

  2. On the main menu, point to Tools, click Forms, and then click Design A Form.

  3. Select Contact, and then click Open, as shown in Figure 13-14.

    Figure 13-14. Design Form dialog box with Contact selected

    Design Form dialog box with Contact selected

  4. In the Design group, click Form Region, and then click New Form Region. Figure 13-15 shows the form designer with a new empty form region.

    Figure 13-15. Designing a new form region

    Designing a new form region

Outlook creates a tab in the Forms Designer titled (Form Region). This tab is now a new form region design surface that you use to design the form region, saving it as an Outlook Form Storage (.ofs) file. For this solution, you need three text boxes, three buttons, one Outlook Business Card Control, one Outlook ComboBox Control, six labels, one Outlook Frame Header Control, and one list box.

To add these controls to the form, follow these steps:

  1. Display the Control Toolbox by going to the Design group of the Office Fluent Ribbon and clicking the Control Toolbox button.

  2. Right-click the Control Toolbox, and select Custom Controls.

  3. Scroll through the list of controls, select the following controls, and click OK.

    • Microsoft Office Outlook Command Button Control

    • Microsoft Office Outlook List Control

    • Microsoft Office Outlook TextBox Control

    • Microsoft Office Outlook Frame Header Control

    • Microsoft Office Outlook Business Card Control

    • Microsoft Office Outlook Label Control

    • Microsoft Office Outlook ComboBox Control

  4. Drag these controls to the form, and arrange them to look like Figure 13-13.

  5. To adjust the properties of each control, including the control name and caption, right-click each control, and select Properties. For each control, keep the default settings and adjust the properties accordingly:

    • Full Name text box

    • Layout: Horizontal: Grow/shrink with form

    • Value: bound to Full Name field

    • Frequent Flyer text box

    • Name: TextBoxFFN

    • Layout: Horizontal: Grow/shrink with form

    • Value: bound to FrequentFlyerNumber (new Text field)

    • Seat Preference combo box

    • Name: ComboBoxSeatPref

    • Layout: Horizontal: Grow/shrink with form

    • Value: bound to SeatPreference

    • Value: List Type: Droplist

    • Value: Possible values: Window;Aisle;Middle

    • Preferred Airline text box

    • Name: TextBoxPreferredAirline

    • Layout: Horizontal: Grow/shrink with form

    • Value: bound to PreferredAirline (new Text field)

    • Last Purchased text box

    • Name: TextBoxLastPurchase

    • Layout: Horizontal: Grow/shrink with form

    • Value: bound to LastPurchaseDate (new Date/Time field)

    • Frame Header Control

    • Name: FrameHeaderItineraries

    • Caption: Itineraries

    • Layout: Horizontal: Grow/shrink with form

    • Itineraries list box

    • Name: listItineraries

    • Layout: Horizontal: Grow/shrink with form

    • Layout: Minimum width: 100

    • Layout: Vertical: Grow/shrink with form

    • New Itinerary command button

    • Name: ButtonNewItinerary

    • Caption: &New Itinerary

    • Edit Itinerary command button

    • Name: ButtonEditItinerary

    • Caption: &Edit Itinerary

    • Delete Itinerary command button

    • Name: ButtonDeleteItinerary

    • Caption: &Delete Itinerary

  6. To save the form region, on the Developer tab in the Design group, click Form Region, and then click Save Form Region As.

  7. Save the new form region in a folder as TravelAgencyRegion.ofs, and close the window. When Outlook prompts you to save the changes to the item underlying the designer, click No. We'll import this file later into our add-in project.

Step 2: Writing Business Logic

Now that the design of the form region is complete, you need to craft the add-in that will run in Outlook and provide the business logic for the form. First, you write the basic form region hookup code, which involves implementing and handling an interface defined by Outlook. To encapsulate the business logic for a form region, you will create a form region wrapper class that maintains state for an instance of a form region.

Hooking Up a Form Region and an Add-In

To get started, you need to create a new add-in in Microsoft Visual Studio using either the Shared Add-in template or the Outlook 2007 Add-in template provided on this book's companion Web site. For the purposes of this example, name the project TravelAgencyAddinCS. After the project has been created, you should have a Connect.cs file that contains the Connect class of your add-in.

Before you continue, you must add a few references to the project. If you are using the template that comes with this book, you should already have references for the Outlook and Office type libraries. If you are using the Shared Add-in template, you must add these references. You will also need to add a reference to the Microsoft Forms 2.0 type library (Fm20.dll) in either case.

Inside the Connect class, you implement the FormRegionStartup interface, which is the interface Outlook will use to communicate with the add-in about any form regions tied to the add-in. This interface includes two methods: GetFormRegionStorage and BeforeFormRegionShow, which are called when Outlook is requesting the OFS file for the form region and just before the form region is displayed to the user, respectively. To implement this interface, change the definition of the Connect class to look like this.

public partial class Connect : Outlook.FormRegionStartup

If you are using the Shared Add-in template, you need to create an alias for the Outlook namespace to refer to the interface in this way by adding this line to the top of the file.

using Outlook = Microsoft.Office.Interop.Outlook;

Next, you should have Visual Studio generate the method prototypes for the interface. Right-click the FormRegionStartup text, and select Implement Interface from the context menu. Visual Studio then creates the prototypes for the two methods, and you can start writing the code to handle these methods.

Implementing GetFormRegionStorage

Because GetFormRegionStorage is called first, you will start with this method. Outlook will accept a number of return values from this method, depending on how your solution works. Outlook is looking for one of the following resources to supply the form region storage:

  • An absolute file path (in the form of a string) to the OFS file

  • A byte array containing the contents of the OFS file

  • An IStorage instance that contains the contents of the OFS file

From managed code, the best mechanism to use is the byte array, because Visual Studio will natively generate the appropriate code when the OFS file is added as a resource for the project.

To add the form region storage to the project as a resource, in the Project Explorer, right-click the Project node, and select Properties to open the Properties window for the project. Click the Resources tab, and create a new default resource file by selecting the hyperlink. Press CTRL+5 to switch to the File resources display, which should be empty at this point. Click Add Resource on the toolbar, and then find and open the OFS file for the form region you designed and saved in Step 1. Visual Studio automatically copies the OFS file into a Resources folder in the project and creates a new resource variable for the file. Figure 13-16 shows what the resource editor should look like after the file is added.

Figure 13-16. Visual Studio project resources with the form region file added as a resource

Visual Studio project resources

Close the Properties window to return to the source code for the Connect class, where you can now return the resource during the GetFormRegionStorage method. To ensure that you return the right resource for the right form region (or to handle multiple form regions), use a switch statement to switch based on the FormRegionName property.

public object GetFormRegionStorage(string FormRegionName, object Item, 
    int LCID, Outlook.OlFormRegionMode FormRegionMode, 
    Outlook.OlFormRegionSize FormRegionSize) 
{ 
    switch (FormRegionName) 
    { 
        case "TravelAgencyRegion": 
            return Properties.Resources.TravelAgencyRegion; 
 
        default: 
            return null; 
    } 
}

Because Visual Studio automatically creates a new property for each resource added to the project's resources, and assumes that binary files should be returned as a byte array, no additional code is required in the GetFormRegionStorage method of the interface. To handle other form regions, just add more case statements to the switch block for each form region name.

  • Implementing a Form Region Wrapper

Because Outlook can have multiple windows open at a time, and each window could show an instance of the same form region type, you need a wrapper class that will track the state of a particular instance.

Because several elements of the form region wrapper will be the same across different form regions, you use a base class to implement these details, and then you can create another class that derives from the base class to manage the business logic and variables for a specific type of form region. To get started, create the base class, BaseFormRegionWrapper. Add a new class file to the project, and type BaseFormRegionWrapper for the name of the class. To the top of the class file, add using directives for the Outlook object model and the Microsoft Forms 2.0 object model.

using Outlook = Microsoft.Office.Interop.Outlook; 
using Forms = Microsoft.Vbe.Interop.Forms;

Next, edit the class file to contain the following code. This code will create instance variables to hold on to the FormRegion instance, hold on to the UserForm instance, and provide a Close event that will be raised when the form region is closed. The class also implements IDisposable to clean up the native code references for FormRegion and UserForm when the object is disposed.

abstract class BaseFormRegionWrapper : IDisposable 
{ 
    #region Instance Variables 
    private bool disposed = false; 
    protected object Item; 
    protected Outlook.FormRegion FormRegion; 
    protected Forms.UserForm UserForm; 
    #endregion 
    #region Constructor 
    public BaseFormRegionWrapper(Outlook.FormRegion region) 
    { 
        this.Item = region.Item; 
        this.FormRegion = region; 
        this.UserForm = FormRegion.Form as Forms.UserForm; 
        this.FormRegion.Close +=  
        new Outlook.FormRegionEvents_CloseEventHandler( 
        FormRegion_Close); 
    } 
    #endregion 
    #region Events/Handlers 
    /// <summary> 
    /// Event is raised when the wrapped form region raises 
    /// its close event 
    /// </summary> 
    public event EventHandler Close; 
 
    /// <summary> 
    /// Raises the close event on this class 
    /// </summary> 
    protected virtual void OnFormRegionClose() 
    { 
        if (Close != null) 
        { 
            Close(this, EventArgs.Empty); 
        } 
    } 
 
    private void FormRegion_Close() 
    { 
        OnFormRegionClose(); 
    } 
 
    #endregion 
    #region IDisposable Members 
 
    ~BaseFormRegionWrapper() 
    { 
        // Call Dispose with false. Because we're in the 
        // destructor call, the managed resources will be 
        // disposed of anyway. 
        Dispose(false); 
    } 
 
    public void Dispose() 
    { 
        // Dispose of managed & unmanaged resources. 
        Dispose(true); 
 
        // Tell the GC that the Finalize process no longer needs 
        // to be run for this object. 
        GC.SuppressFinalize(this); 
    } 
 
    protected void Dispose(bool disposeManagedResources) 
    { 
        // Process only if managed and unmanaged resources have 
        // not been disposed of. 
        if (!this.disposed) 
        { 
            if (disposeManagedResources) 
            { 
                // Dispose managed resources.
                Item = null; 
            } 
 
            if (FormRegion != null) 
            { 
                 
System.Runtime.InteropServices.Marshal.ReleaseComObject(FormRegion); 
                FormRegion = null; 
            } 
            if (UserForm != null) 
            { 
                 
System.Runtime.InteropServices.Marshal.ReleaseComObject(UserForm); 
                UserForm = null; 
            } 
 
            disposed = true; 
        } 
    } 
 
    #endregion 
}

Now that you have the base class defined for the form region wrapper, you need to create a class for your specific form region. In this case, you want to handle the form region state while the form region is open and implement your business logic. To do this, add a new class file named ContactFormRegionWrapper, which will contain the business logic implementation for this form region.

Inside the ContactFormRegionWrapper class, you will create instance variables for every control on the form and hook up those variables during the constructor for the class. You will then implement some business logic around those controls and provide data for the list of itineraries from a data source.

To get started, you need to define variables for all the form controls on the form. To start, you should add namespace aliases, so insert the following lines at the top of the new class file.

using Outlook = Microsoft.Office.Interop.Outlook; 
using Office = Microsoft.Office.Core; 
using Forms = Microsoft.Vbe.Interop.Forms;

You also want to make sure that the new ContactFormRegionWrapper class derives from the BaseFormRegionWrapper class that you wrote previously. This provides the basic functionality around handling the closing of the form region. To derive from this class, change the class definition to look like this.

class ContactFormRegionWrapper : BaseFormRegionWrapper

You will continue to define the rest of the methods in the ContactFormRegionWrapper class in a bit, but first, to keep track of the itinerary state, you need to have a data class. In this case, you create a new class named Itinerary and define properties for the fields that you want to keep track of. In this case, you should create a simple data class with the following fields:

string DepartingAirport, string ArrivingAirport, DateTime DepartureDate, DateTime ArrivalDate, string Airline, and string FlightNumber.

You should consider overriding the ToString() method of the class to provide a representative view of the data, as this is the way the item will be displayed to the user.

Now that you have a data class, you should switch back to working on the ContactFormRegionWrapper class. To provide an easy reference to the form controls, define a variable for each control on the form (or at least the controls that are important in the business logic you will write). In this case, you'll add variables for all the controls to the class. You'll also add another variable to maintain a list of available itinerary information.

private Outlook.OlkLabel LabelFFN; 
private Outlook.OlkTextBox TextBoxFFN; 
private Outlook.OlkLabel LabelPreferredAirline; 
private Outlook.OlkTextBox TextBoxPreferredAirline; 
private Outlook.OlkLabel LabelSeatPref; 
private Outlook.OlkComboBox ComboBoxSeatPref; 
private Outlook.OlkLabel LabelLastPurchase; 
private Outlook.OlkTextBox TextBoxLastPurchase; 
private Outlook.OlkCommandButton ButtonNewItinerary; 
private Outlook.OlkCommandButton ButtonEditItinerary; 
private Outlook.OlkCommandButton ButtonDeleteItinerary; 
private Outlook.OlkListBox ListItineraries; 
private List<Itinerary> Itineraries;

Next up is the constructor for this helper class, which will extend the base constructor provided in BaseFormRegionWrapper to actually initialize the member variables for this particular form region. In the constructor you call two helper methods, one to initialize the control variables just defined and another to load itinerary information from the data source. The code should look something like this.

public ContactFormRegionWrapper(Outlook.FormRegion region) : base(region) 
{ 
    Itineraries = new List<Itinerary>(); 
    // Initialize controls.
    InitializeControls(); 
    // Load data from persistence.
    LoadItineraries(); 
} 

Next, you need to write the helper function InitializeControls that will take the instances available on the user form and map them down to the instance variables and cast them to the appropriate type. At the same time, you will wire up some event handlers that will handle the events that you must listen for on these controls.

void InitalizeControls()
{
    try
    {
        // Locate control references.
        LabelFFN = 
            UserForm.Controls.Item("LabelFFN") as Outlook.OlkLabel;
        TextBoxFFN = 
            UserForm.Controls.Item("TextBoxFFN") as Outlook.OlkTextBox;
        LabelPreferredAirline = 
            UserForm.Controls.Item("LabelPreferredAirline") 
            as Outlook.OlkLabel;
        TextBoxPreferredAirline = 
            UserForm.Controls.Item("TextBoxPreferredAirline") 
            as Outlook.OlkTextBox;
        LabelSeatPref = 
            UserForm.Controls.Item("LabelSeatPref") 
            as Outlook.OlkLabel;
        ComboBoxSeatPref = 
            UserForm.Controls.Item("ComboBoxSeatPref") 
            as Outlook.OlkComboBox;
        LabelLastPurchase = 
            UserForm.Controls.Item("LabelLastPurchase") 
            as Outlook.OlkLabel;
        TextBoxLastPurchase = 
            UserForm.Controls.Item("TextBoxLastPurchase") 
            as Outlook.OlkTextBox;
        ButtonNewItinerary = 
            UserForm.Controls.Item("ButtonNewItinerary") 
            as Outlook.OlkCommandButton;
        ButtonEditItinerary = 
            UserForm.Controls.Item("ButtonEditItinerary") 
            as Outlook.OlkCommandButton;
        ButtonDeleteItinerary = 
            UserForm.Controls.Item("ButtonDeleteItinerary") 
            as Outlook.OlkCommandButton;
        ListItineraries = 
            UserForm.Controls.Item("listItineraries") 
            as Outlook.OlkListBox;
        Forms.Frame Frame2 = 
            UserForm.Controls.Item("Frame2") as Forms.Frame;
        Frame2.BorderStyle = 
            Microsoft.Vbe.Interop.Forms.fmBorderStyle.
            fmBorderStyleNone;
        Frame2.ScrollBars = 
            Microsoft.Vbe.Interop.Forms.fmScrollBars.fmScrollBarsNone;

        // Hook up events.
        ButtonNewItinerary.Click += 
            new Outlook.OlkCommandButtonEvents_ClickEventHandler(
            ButtonNewItinerary_Click);
        ButtonEditItinerary.Click += 
            new Outlook.OlkCommandButtonEvents_ClickEventHandler(
            ButtonEditItinerary_Click);
        ButtonDeleteItinerary.Click += 
            new Outlook.OlkCommandButtonEvents_ClickEventHandler(
            ButtonDeleteItinerary_Click);
        ListItineraries.DoubleClick += 
            new Outlook.OlkListBoxEvents_DoubleClickEventHandler(
            ListItineraries_DoubleClick);
    }
    catch (Exception ex)
    {
        Debug.WriteLine ("An error occured while hooking up 
        Form Region controls: " + ex.Message);
    }
}

Now that you have all that glue out of the way, you can actually start writing the business logic. In this case, you'll be using a file named Itineraries.xml to maintain information about a given contact's itineraries. This file will live as a hidden attachment on the contact. In a real-world solution, you might use a database connection or Web service to retrieve this data from a server, but the basic form region code would look similar.

The LoadItineraries method called in the constructor looks for an attachment on the Contact with a particular file name (in this case Itineraries.xml) and then deserializes the contents of that file back into an instance of a List class containing the itineraries. If the attachment does not exist, an empty list will be created and the file will be created when the contact is saved if any itineraries are added while the form region is open. This method can be downloaded as part of the sample code available for the book and is not printed here.

Now that the form initialization code is finished, you can write the event handlers that you wired up in the InitializeControls method previously. These events handle adding a new itinerary, editing an existing itinerary, and deleting an itinerary. When the event fires, you display a Windows Forms dialog box that allows the user to create or edit an itinerary object, which is added back to the Itineraries List object after the user clicks OK. Because this code does not directly affect the operation of the form region, it is not included here but can be downloaded from this book's companion Web site.

Each of these event handlers also saves the changes back to the attached XML file after making the change to the list so that the file is always in sync with the displayed list of itineraries. Because the file attachment is not saved if the user cancels making changes to the item, this behavior is still consistent with the way Outlook behaves. If you are using a database or other back-end store, you might want to wait for the Save event to occur on the item before persisting the changes to the back-end store so that if a user cancels saving the item, the item remains in a consistent state.

Step 3: Registering the Form Region

Once you have the business logic written and the form design complete, you can write the manifest file and register the form region. The manifest file describes the form region to Outlook and includes details about where to load the form region layout file, which icons to display, and any custom actions that should be added to the item. After the manifest is created, it is registered in the Windows registry under registry keys for each message class that should load the form region.

Authoring a Form Region Manifest

The form region manifest file is a simple XML file described as the Form Region Manifest XML Schema, which is available as part of the 2007 Microsoft Office system XML Reference on MSDN. The following sections provide a quick overview of the important schema elements.

  • **Manifest Basics   **Each form region manifest is composed of one document element, the <FormRegion> element, which has several child elements that are mostly optional. Default values are assumed for any element that is not included in the manifest file, and these default values are defined in the XML schema for the manifest. If no <name> element is provided, the name of the registry value for the form region will be used instead. The following is a relatively simple manifest example, which provides a name, type, page name, accelerator key, add-in, and an icon for the form region that appears in the Show group in the Office Fluent Ribbon.

    <?xml version="1.0" encoding="utf-8"?> 
    <FormRegion xmlns="http://schemas.microsoft.com/office/outlook/12/formregion.xsd"> 
        <name>TravelAgencyRegion</name> 
        <formRegionType>separate</formRegionType> 
        <formRegionName>Itineraries</formRegionName> 
        <ribbonAccelerator>I</ribbonAccelerator> 
        <showInspectorCompose>true</showInspectorCompose> 
        <showInspectorRead>true</showInspectorRead> 
        <showReadingPane>false</showReadingPane> 
        <addin>TravelAgencyAddinCS.Connect</addin> 
        <icons> 
            <page>plane.png</page>   
        </icons> 
        <stringOverride file="TravelAgencyRegionCS.%langid%.xml" language="all" /> 
    </FormRegion>
    
  • **Optional Elements   **Each of the following elements is optional and will have the default value assumed if it is not specified in the manifest XML. Each of these elements should be a child of the <FormRegion> element if included, and should only appear once.

    • <name>   The internal name of the add-in. This value is passed to the GetFormRegionStorage and BeforeFormRegionStartup methods to identify this form region. It can also be used in other form region <displayAfter> elements.

    • <title>   The title of the form region, which is displayed in the Choose Form dialog box and the Actions menu for replacement and replace-all forms. This title is also displayed for adjoining form regions as the header name above the form region. <name> will be used if this value is not included.

    • <formRegionName>   The text displayed on the Show group on the Office Fluent Ribbon for this form region (only valid for separate, replacement, and replace-all form regions). <title> will be used if this value is not included.

    • <description>   Text that describes the use of the form region, displayed in the Choose Form dialog box.

    • <formRegionType>   Specifies the type of form region. Must be separate, adjoining, replace, or replace-all.

    • <showInspectorCompose>   Controls if this form region is displayed in the Inspector window in compose mode for this item type. Default value is True.

    • <showInspectorRead>   Controls if this form region is displayed in the Inspector window in read mode for this item type. Not all item types have a read mode. Default value is True.

    • <showReadingPane>   Controls if this form region is displayed in the Reading Pane for this item type. Only affects adjoining, replacement, and replace-all form regions.

    • <hidden>   Controls if the form region title is displayed in the Choose Form dialog box and Actions menu. The default value is False. Only works for replacement and replace-all form regions.

    • <exactMessageClass>   Controls how the form region behaves on derived message classes. Default value is False. When True, the form region will only be displayed on message classes that match exactly how it was registered; otherwise, message classes that are derived from the original registration will also display this form region.

    • <layoutFile>   Specifies the OFS file that Outlook should load to display this form region. This value is only used if <addin> is not specified.

    • <addin>   Specifies the ProgID or identifier for the add-in that should be called for this form region. The add-in must implement the FormRegionStartup interface to be called.

    • <displayAfter>   Specifies the name of another form region that this form region should be positioned after. This does not guarantee that the form region directly preceding this one will be the one specified, based on load order and other form regions that might have the same <displayAfter> value.

    • <contact>   Specifies a contact name for the form region. This information can be used for supportability of a form region.

    • <version>   Specifies a version of the form region. This information can be used for supportability of a form region.

    • <loadLegacyForm>   This option determines whether Outlook looks for a custom form with form pages with the same message class if it finds a form region first. This value defaults to False and, for performance reasons, should remain False unless you need to load form pages and form regions at the same time.

    • <ribbonAccelerator>   Specifies one to three characters that should be used as the hot key for the form region's Office Fluent Ribbon button. This value is ignored for adjoining form regions.

    • <icons>   Specifies custom icons for the item type. For more information, see the section "Custom Icons" later in this chapter.

    • <customActions>   Specifies custom actions for the item type. For more information, see the section "Describing Custom Actions" later in this chapter.

    • <stringOverride>   Specifies localized strings that can be used for a particular language. For more information on localizing form regions, see the section "Localizing a Form Region" later in this chapter.

Custom Icons

Replacement and replace-all form regions can specify a range of custom icons that are shown when items of the form region message class are displayed in the view. Additionally, separate form regions can specify an icon that shows up in the Office Fluent Ribbon on the button to activate that form region page. All of these icons are specified in the <icons> element of the <FormRegion> element in the manifest. Table 13-4 lists custom icon elements.

If you include the <icons> element in your form region manifest, you should include at least one child element. Each child element represents a particular icon visible to the user somewhere in Outlook. Each child element should contain either (a) a path to the icon file or (b) a path to a dynamic-link library (DLL) and a resource number to load from the file. Relative paths are resolved against the location of the manifest XML file. For example:

<FormRegion xmlns="http://schemas.microsoft.com/office/outlook/12/formregion.xsd"> 
    <icons> 
        <!-- relative path --> 
        <default>icons\default.ico</default> 
        <!-- embedded resource --> 
        <window>%SystemRoot%\system32\SHELL32.dll,102</window> 
        <!-- relative path to bitmap --> 
        <page>icons\plane.png</page>   
    </icons> 
</FormRegion>

Table 13-4. Custom icon elements

Element name

Description

Supported

format

Applies to

<default>

An icon that will be used by default when no other icon is provided, except for the <page> icon.

ICO only

Replacement and replace-all form regions only.

<unread>

An icon displayed in the Folder view for unread items.

ICO only

Replacement and replace-all form regions only.

<read>

An icon displayed in the Folder view for read items.

ICO only

Replacement and replace-all form regions only.

<replied>

An icon displayed in the Folder view for items that have been replied to.

ICO only

Replacement and replace-all form regions only.

<forwarded>

An icon displayed in the Folder view for items that have been forwarded.

ICO only

Replacement and replace-all form regions only.

<unsent>

An icon displayed in the Folder view for items that are unsent, which are typically found in the Drafts folder.

ICO only

Replacement and replace-all form regions only.

<submitted>

An icon displayed in the Folder view for items that have been submitted for sending, but are not yet sent; these are typically found in the Outbox.

ICO only

Replacement and replace-all form regions only.

<signed>

An icon displayed in the Folder view for items that have been digitally signed.

ICO only

Replacement and replace-all form regions only.

<encrypted>

An icon displayed in the Folder view for items that have been encrypted.

ICO only

Replacement and replace-all form regions only.

<window>

An icon displayed for the item Inspector window when the form is open, displayed in the Windows Taskbar and Alt+Tab dialog box.

ICO only

Replacement and replace-all form regions only.

<recurring>

An icon displayed in the Folder view for items that are recurring items, such as recurring tasks or appointments.

ICO only

Replacement and replace-all form regions only.

<page>

An icon or bitmap displayed in the Office Fluent Ribbon on the button to switch to the form region.

ICO or PNG

Separate, replacement, and replace-all form regions.

Describing Custom Actions

Each form region can have custom actions included as part of the form as well. These custom actions work in a manner similar to the built-in actions provided by the standard Outlook forms (for example, Reply, Reply All, Forward). You can also use custom actions to disable the built-in actions if they are not applicable to your custom form.

Custom actions are defined using the <customActions> element, which is always a child of the <FormRegion> element. Under the <customActions> element, you can define individual actions for the form or disable built-in actions. For example, if you wanted to create a new action titled "Post Reply" that would create a new post item in the form of a reply to the current item, the XML in your form region manifest would look like this.

<FormRegion xmlns="http://schemas.microsoft.com/office/outlook/12/formregion.xsd"> 
    <!-- Other elements would go here --> 
    <customActions> 
        <action name="postReply"> 
            <title>Post Reply</title> 
            <targetForm>IPM.Post</targetForm> 
            <addressLike>reply</addressLike> 
            <body>user</body> 
            <showOnRibbon>true</showOnRibbon> 
            <method>open</method> 
            <subjectPrefix>RE</subjectPrefix> 
        </action> 
    </customActions> 
</FormRegion>

This action would then be available via the Actions collection in the object model and on the Office Fluent Ribbon under the Custom Actions menu to allow the user to execute the action.

Each <action> element must have a name attribute that specifies an internal name for the action. This value must be unique across the actions defined for a form region. This value can be used to provide localized strings using the <stringOverride> element. Additionally, the following elements are defined as child elements for the <action> element:

  • <title>

    The display text for the custom action. This value will be shown in the Office Fluent Ribbon and other locations where the action is displayed.

  • <targetForm>

    Specifies the message class of the target form for the action. When the action is executed, a new item will be created with this message class.

  • <addressLike>

    Specifies how the target form will be addressed. Possible values are reply, replyAll, forward, replyToFolder, and response. For more information about the meaning of these values, see the XML schema for form regions.

  • <body>

    Specifies how the body of the target form should be set. Possible values are omit, attach, include, indent, prefix, link, and user. For more information about the meaning of these values, see the XML schema for form regions.

  • <showOnRibbon>

    Boolean value that determines if the custom action is displayed on the Office Fluent Ribbon in the Custom Actions menu.

  • <method>

    Specifies the method Outlook will use when creating the target form. The value of this element should be either open, prompt, or send. For more information about the meaning of these values, see the XML schema for form regions.

  • <subjectPrefix>

    Specifies the characters that will be pre-pended to the subject when creating the target form. For a reply, this might be "RE."

You can also disable any of the built-in actions by defining an action named with a particular keyword. The keywords shown in Table 13-5 are the same regardless of the language in which Outlook is running.

Table 13-5. Custom action name keywords for built-in actions

Name keyword

Action name

Reply

Reply

replyAll

Reply All

forward

Forward

replyToFolder

Reply to Folder

To disable the Reply All action for a form region, you could use the following XML in your manifest file.

<FormRegion xmlns="http://schemas.microsoft.com/office/outlook/12/formregion.xsd"> 
    <!-- Other elements would go here --> 
    <customActions> 
        <action name="replyAll" disable="true"></action> 
    </customActions> 
</FormRegion>

Localizing a Form Region

Form regions include a built-in mechanism to enable localization of form region data (title, description, and so on), as well as the strings displayed on a form region's controls. All of this information can be defined in the manifest file, or you can reference an external localization manifest from the form region manifest where these values can be loaded.

  • **Using String Overrides   **To localize a form region, you can use the <stringOverride> element in the form region manifest file. This element contains child elements that redefine the displayed strings defined in the manifest file for a particular language. Each <stringOverride> element has one required attribute, language, which contains a list of the Locale IDs (LCIDs) of each language that should use the strings defined inside the element.

    For example, to provide localized string information for U.S. English, you could add this XML to your form region manifest.

    <FormRegion> 
        <!-- other elements here --> 
        <stringOverride language="1033"> 
            <title>US English Title</title> 
            <formRegionName>US English Page Name</formRegionName> 
            <description>US English Description</description> 
    
            <control name="OlkLabel1"> 
                <caption>English Display Text</caption> 
            </control> 
    
            <action name="postReply"> 
                <title>English Post Reply</title> 
                <subjectPrefix>US-FW</subjectPrefix> 
            </action> 
        </stringOverride> 
    </FormRegion>
    

    The following elements are defined in the schema for use inside the <stringOverride> element:

    • <title>   The title of the form region, which is displayed in the Choose Form dialog box and the Actions menu for replacement and replace-all form regions. This title is also displayed for adjoining form regions as the header name above the form region. <name> will be used if this value is not included.

    • <FormRegionName>   The text displayed on the Office Fluent Ribbon in the Show group for this form region (only valid for separate, replacement, and replace-all form regions). <title> will be used if this value is not included.

    • <description>   Text that describes the use of the form region, displayed in the Choose Form dialog box.

    • <control>   Represents strings that will be used for a given control on the form region. The name attribute is required on this element and should provide the value of the Name property of the control referenced from the form region.

    • <caption>   A child element of control, this element contains the text that will be set as the Caption property of the control referenced by the name attribute.

    • <action>   Represents strings that will be used for a given custom action on the form region. The name attribute is required on this element and should be the value of the name attribute on the custom action.

    • <title>   A child element of action, this element contains the text that will be used for the localized title of the custom action.

    • <subjectPrefix>   A child element of action, this element contains the text that will be used for the localized subject preview of the custom action.

    Additionally, instead of including all the localized resources in one file, you can use an optional attribute on the <stringOverride> element to point Outlook to another file that contains the resources. In the next example, the <stringOverride> element redirects all languages to look for a file in a directory based on the LCID of the language.

    <FormRegion> 
        <!-- other elements here --> 
        <stringOverride language="all" 
            file="%LCID%\resources.xml"></stringOverride> 
    </FormRegion>
    

    Outlook will replace the %LCID% value in the file attribute with the actual LCID for the language being loaded. Outlook will look up relative paths based on the location of the manifest XML file. In this case, to provide resources for U.S. English, you can create a subdirectory in the same location as the manifest XML file named 1033. Inside this folder, you should have a Resources.xml file that contains this XML.

    <FormRegionStrings xmlns="http://schemas.microsoft.com/office/outlook/12/formregionstrings.xsd"> 
        <title>US English Title</title> 
        <formRegionName>US English Page Name</formRegionName> 
        <description>US English Description</description> 
    
        <control name="OlkLabel1"> 
            <caption>English Display Text</caption> 
        </control> 
    
        <action name="postReply"> 
            <title>English Post Reply</title> 
            <subjectPrefix>US-FW</subjectPrefix> 
        </action> 
    </FormRegionStrings>
    
    NoteNote

    The resource files use a document element named FormRegionStrings instead of FormRegion. The child elements for <FormRegionStrings> are identical to the contents of the <stringOverride> element in the form region manifest.

Registering a Form Region

Each form region has to be registered in the Windows registry before Outlook will load and display the form region. The registration process is a simple matter of writing the correct registry key for the form region message class and specifying the location of the manifest file.

Form regions are registered under the key HKEY_CURRENT_USER\Software\Microsoft \Office\Outlook\FormRegions, or HKEY_LOCAL_MACHINE\Software\Microsoft \Office\Outlook\FormRegions. Most solutions should use the user-based key so that administrative privileges are not required to install the solution. Under the FormRegions key in the registry, you will need to create a key for each message class with which your form region will be used. For example, to register a form region on IPM.Contact, you would create HKEY_CURRENT_USER\Software\Microsoft\Office\Outlook\FormRegions \IPM.Contact and then create a new value under that key. To register a form region on a custom message class, create a new key under the FormRegions key with the name of the message class (see Figure 13-17).

Figure 13-17. Registry editor showing a form region registered on a custom message class

Registry editor showing a form region registered

The value for your form region should be the name of the form region (as defined in the <name> element of the manifest) and the full path to the XML manifest file. The path name can also use environment variables that will be expanded when the value is read; for example, to specify a manifest file from the program files folder, you could use %ProgramFiles%\Solution \MyManifest.xml as the value.

Replacing the Default Form for a Folder

For replacement or replace-all form regions, you can make a form region become the default form for a folder. If the form region is the default form for a folder, the form region is displayed to the user when he or she performs any of the following actions in the folder:

  • Clicks the New button on the Standard toolbar in the Explorer window.

  • Selects the New <Item> command on the New menu on the Standard toolbar in the Explorer window, where <Item> represents the built-in item type for a folder. If the built-in item type is Contact, then selecting New Contact on the New menu in the Explorer window will display the form region.

  • Selects the New <Item> command on the View context menu in the Explorer window, where <Item> represents the built-in item type for a folder.

  • Presses CTRL+N to create a new default item for the folder.

  • Clicks the "new item row" in a Folder view. To show the "new item row" in a view, set the ShowNewItemRow property of the TableView object to True.

NoteNote

Changing the default form for a folder does not change the default form when the user selects New <Item> from the Office menu in an Inspector window. If you want to ensure that your replacement or replace-all form region appears when the user selects the New <Item> command in an Inspector window, monitor the NewInspector and Item_Open events. In the Item_Open event, you cancel the display of the built-in form and then create an instance of the replacement or replace-all form region by calling the Add method of the Items collection. For additional details on creating a custom item, see the section "Creating an Item" in Chapter 5, "Built-in Item Types."

Although the Folder object does not implement a method that lets you set the default form for a folder directly, you can use the PropertyAccessor object to set the correct folder properties. The following code example shows you how to set the default form for a folder. The DemoSetDefaultFormForFolder method sets the default form for the current folder to "Shoe Store" by calling the SetDefaultFormForFolder method. The message class for the "Shoe Store" replacement form region is "IPM.Contact.Shoe Store."

private void DemoCustomDefaultFormForFolder() 
{ 
    Outlook.Folder folder =  
        Application.ActiveExplorer().CurrentFolder as Outlook.Folder; 
    SetDefaultFormForFolder( 
        "IPM.Contact.Shoe Store", "Shoe Store", folder); 
} 

 private void SetDefaultFormForFolder(string defaultMessageClass, 
    string defaultDisplayName, Outlook.Folder folder) 
{ 
    const string PR_DEF_POST_MSGCLASS =  
        "http://schemas.microsoft.com/mapi/proptag/0x36E5001E"; 
    const string PR_DEF_POST_DISPLAYNAME =  
        "http://schemas.microsoft.com/mapi/proptag/0x36E6001E"; 
    if (folder == null) 
    { 
        throw new ArgumentNullException( 
            "folder", "Parameter must contain a value."); 
    } 
    if(string.IsNullOrEmpty(defaultMessageClass)) 
    { 
        throw new ArgumentNullException( 
            "defaultMessageClass",  
            "Parameter must contain a value."); 
    } 
    if (string.IsNullOrEmpty(defaultDisplayName)) 
    { 
        throw new ArgumentNullException( 
            "defaultDisplayName", 
            "Parameter must contain a value."); 
    } 
    try 
    { 
        // Calling SetProperty sets the property without saving.
        folder.PropertyAccessor.SetProperty( 
            PR_DEF_POST_DISPLAYNAME, defaultDisplayName); 
        folder.PropertyAccessor.SetProperty( 
            PR_DEF_POST_MSGCLASS, defaultMessageClass); 
    } 
    catch (Exception ex) 
    { 
        Debug.WriteLine(ex.Message); 
    } 
}

To reset the default form for a folder, you call the SetDefaultFormForFolder method and pass the DefaultMessageClass property for the Folder object as the defaultMessageClass argument. The DefaultMessageClass property always returns the built-in default message class for a folder rather than a custom message class such as "IPM.Contact.Shoe Store." The following code sample resets the default message class for the current folder.

private void DemoResetDefaultFormForFolder() 
{ 
    Outlook.Folder folder = 
        Application.ActiveExplorer().CurrentFolder as Outlook.Folder; 
    SetDefaultFormForFolder( 
        folder.DefaultMessageClass, " ", folder); 
}

Advanced Form Region Methods

In addition to the methods described earlier in the FormRegionStartup interface, there are two other methods provided on this interface: GetFormRegionManifest and GetFormRegionIcon. Advanced form region developers can use these methods to let the add-in provide all of the content Outlook needs for the form region: the manifest file, the icons, and the form storage. This allows add-ins that cannot reliably know where files are installed to the disk to provide form region solutions, and it also improves the reliability of the solution because all the associated files can be stored as resources inside the compiled assembly.

Outlook will only call these advanced functions if the form region is registered in a special way in the Windows registry. Instead of registering the form region with XML or a path to the XML file as the setting value, add-ins must register their ProgID with an equal sign appended to the front, such as =MyAddingProgID.Class. This indicates to Outlook that it needs to look for this add-in and call the GetFormRegionManifest method on the FormRegionStartup interface to find out more about the registered form region.

When manifest information is provided through GetFormRegionManifest, a few of the elements defined in the form region XML schema are treated differently. For example, the <name> element is ignored from the XML schema because Outlook is already using the registry setting name as the form region name. Additionally, both the <layoutFile> and <addin> attributes are ignored because Outlook already knows which add-in should be contacted for the form region. Finally, the children of the <icons> element cannot be used to refer to a location on disk for the icons. If the child element exists and contains no value or the string addin, then Outlook automatically calls GetFormRegionIcon for that icon. Icons that are completely omitted from the manifest XML will inherit the default icon and will not be requested from GetFormRegionIcon.

Summary

In this chapter, you learned the basics of using the Outlook Forms Designer to create a new form region solution. You've looked at how to design a form, how to hook up the business logic for a form using an add-in in managed code, and how to write a form region manifest file and register it with Outlook. You should now be able to use Outlook form regions to create deeply integrated, rich solutions that really extend the power and usefulness of Outlook while still feeling like an integrated part of the Outlook experience.

Additional Resources