Destination .NET! Platform Tools, Technologies & Resources
1 3 5 7 9
2 4 6 8 10
From VB4, C++ and Java to working on .Net Since Beta, 1.0.
Improving partner satisfaction and accelerating Microsoft platform adoption for managed ISVs.
Is your application compatible with Windows Vista? Make sure today by taking our self-test. Just follow the five steps of the Works with Windows Vista program so that you and your customers can be confident in your solution’s compatibility. Read More >>
What product/topic are you most interested in?
(Choose your top answer.)
Windows Vista
Windows Server 2008
2007 Microsoft Office system
SQL Server 2008
ASP.NET
Visual Studio 2008
Windows Mobile
Software as a Service
A little bit of everything
Just browsing, thanks

View Results
Whether you love the site or hate it, we want to know. Tell us what topics to cover, help us improve things, or just sound off on something we could've done better. Send your feedback directly to the editor by email.
 Print Print
Average Rating: 4.2/5 | Rate this item | 5 users have rated this item.
Outlook the Way You Want It—Build Custom Outlook GUIs with WinForms & VSTO
Learn to build your own custom form for Outlook appointment items. 

Outlook is perhaps the most utilized application within Microsoft Office, as it is the application that provides tools for communication, organization, and collaboration. I keep Outlook open all day because it's my main tool—not only for communication, but also for tracking my tasks and keeping a record of the time I spend on different projects. In this article I will show you a method for tracking time by developing a custom appointment form that replaces the default appointment form provided by Outlook.

This solution is implemented as a VSTO-Outlook add-in. The entire add-in consists of three objects: a WinForm (and its related code), the VSTO-created ThisApplication class, and an XML file.

In this article, you will learn:

  • How to create an Outlook Add-in using Visual Studio Tools for Office (VSTO).
  • How to replace an Outlook form with your own custom form.
  • How to manage the storage and retrieval of data entered into the custom form.

NOTE: the following prerequisites for building the projects in this article:
1. Microsoft .NET Framework 2.0
2. Visual Studio 2005 Beta 2
3. Visual Studio 2005 Tools for Office, Outlook (Beta)
4. Office Professional 2003
5. Office Primary Interop Assemblies (PIAs)

Outlook Forms: Good, But Good Enough?
Outlook has a rich set of default forms just ready for you, as a developer, to customize for your specific needs. Each type of Outlook item (Task, Appointment, Contact, Mail, Note, and Journal) has a related form built to handle the item's unique requirements. Each form can be customized like any other Office UserForm. All the usual suspects are available: Label, TextBox, ComboBox, ListBox, CheckBox, etc.

In fact, building an Outlook form is easier than building a typical WinForm because all you have to do is drag an Outlook field to the form and the control matching the field's data type is drawn. For example, drop the Contacts field on a form in design mode and Outlook will draw a Button and matching TextBox control on the form.

One key drawback to modifying Outlook forms is that you are limited to the forms provided. If you want to build a custom Task form (or any Outlook form), you must start with Outlook's Task form and modify the design. This may work for most solutions, but I have always wanted to build my own form and substitute it in place of the form Outlook provides. This desire is strengthened by the fact that many of the forms do not allow modifications to their primary tab... such as the two forms I most want to customize for my solutions: the Appointment and Task forms!

WARNING: Replacing Outlook's default forms with a WinForm is not supported by Microsoft. This means there is no guarantee this strategy will work with future versions of Outlook or that it will work with all supported Outlook 2003 scenarios. For example, this form does not support many of the features available with the default form.

You Have Control (Maybe You Just Didn't Know It)
Yes, it is true that you can take control of Outlook and pull a "switcheroo" by intercepting the Outlook correct event and showing your own dazzling custom form instead. In order to understand how this is done, an abbreviated study of the Outlook objects required for this solution—the Outlook Object Model—is in order (Figure 1).


Figure 1.
A Simplified View of the Outlook Object Model

Outlook, like all Office applications, has an Application object at the top of the object hierarchy. Beneath this object are the Explorers and Inspectors objects, each containing collections of Explorer and Inspector objects, respectively. These two collections can be confusing as they provide access to the same types of objects within Outlook. That said, they have two separate purposes. To keep it straight, just remember that an Explorer is used to "explore" the items contained within Outlook's folder structure and that an Inspector is used to "inspect" individual Outlook items.

In this article, we will focus on the Inspector object because it contains the NewInspector method, which is triggered every time an Outlook item is opened or created. This applies to tasks, appointments, contacts, e-mails, etc.

Build and Implement a Custom Appointment Form
The first step to this example solution is the custom form that will replace Outlook's AppointmentItem form. My custom form is a WinForm named TyApptItem. This form is a scaled down version of Outlook's appointment form. It's scaled down so that it includes only the fields needed to for creating a time entry (date, start time, end time, etc.). This solution is built utilizing the VSTO Outlook template as follows:

Step 1: Build a Custom Appointment Form
  1. Open Visual Studio 2005 Beta 2.
  2. Select File > New > Project to display the New Project dialog box.
  3. Under Project Types, select Visual Basic > Office.
  4. Select Outlook Add-In from the Templates options.
  5. Name the project OutlookAddin1 and click OK.
  6. Select Project > Add Windows Form. Name it TyApptItem.vb. Click Add.
  7. Draw the following controls onto the form and set their properties accordingly. Use Figure 1 as a guide for designing your version of the form.
    1. 1 ToolStrip Control: Name = tsMenu, Text = ""
    2. 3 Label Controls:
      1. Name = lblSubject, Text = Subject
      2. Name = lblStartDate, Text = Start Date,
      3. Name = lblDueDate, Text = Due Date
    3. 2 TextBox Controls:
      1. Name = txtSubject, TabIndex = 1
      2. Name = txtBody, Multiline = True, TabIndex = 6
    4. 4 DateTimePicker Controls:
      1. Name = dtpStartDate, Format = Long, TabIndex = 2
      2. Name = dtpStartTime, Format = Time, ShowUpDown = True, TabIndex = 3
      3. Name = dtpDueDate, Format = Long, TabIndex = 4
    5. Name = dtpDueTime, Format = Time, ShowUpDown = True, TabIndex = 5
  8. Add four controls to the ToolStrip control by selecting tsMenu. Once the Add ToolStripButton control appears, click it to add three Button controls and one ComboBox control. Change their properties as follows:
    1. The Button Controls:
      1. Name = tsbSaveAndClose, DisplayStyle = ImageAndText, Text = &Save and Close
      2. Name = tsbSave, DisplayStyle = Imaget, Text = &Save
      3. Name = tsbDelete, DisplayStyle = Image, Text = &Delete and Close
      1. The ComboBox Control:
      2. Name = tscboProjects

    Figure 2.
    The TyApptItem form design layout

Hopefully your form resembles something similar to Figure 2. She certainly isn't the most beautiful form out there, but we're not through yet. Using this form, I will now explain the secret to using a custom form in place of any Outlook form.

Step 2: Write Code to Replace Outlook's Default Appointment Form (ThisApplication.vb)
The trick to substituting the default Outlook Appointment form is to capture the NewInspector event. This event resides in the Inspectors collection. By capturing this event, you can intercept the form Outlook would like open, cancel it, and open your form instead. It's pretty simple once you see how it's done. Switching the form is the easy part—the hard part is the code required to handle opening and saving a "switched" item. Even this isn't too difficult, as you will soon find out.

Once you complete Step 2, you will have all the code required for the ThisApplication class. To get started, open ThisApplication.vb and insert the following variable declarations:

  Private WithEvents tyINS As Outlook.Inspectors
  Private WtihEvents tyAI As Outlook.AppointmentItem

These variables provide the needed access to the Inspectors collection and any created AppointmentItem.

ThisApplication_Startup Event
In order to listen for the NewInspector event, the add-in needs access to Outlook's Inspectors collection. The best place to set up a reference to the Inspectors collection is the Startup event of the ThisApplication object.

NOTE: When you created the add-in earlier, VSTO created a class name ThisApplication that inherits the Microsoft.Office.Tools.Outlook.Application namespace and provides project-wide access to the Outlook object model. There is more to it than that, but this is the net result. ThisApplication is contained in a partial class. If you want to check it out further, just click ShowAllFiles in the Solution Explorer.

Insert the following code into the ThisApplication class:

  Private Sub ThisApplication_Startup(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Me.Startup

    tyINS = Me.Inspectors
  End Sub

This method will fire as part of Outlook's initialization and store a reference to Outlook's Inspectors collection. Since tyINS was declared WithEvents it will allow us to listen for, and respond to, the NewInspector event.

The NewInspector Event
The NewInspector event fires every time an Outlook form opens. It doesn't matter if the form is opened by a user or through code, this event will be triggered. Therefore, the NewInspector event is the place for the code that displays the TyApptItem form.

  Private Sub tyINS_NewInspector(ByVal Inspector As _
    Microsoft.Office.Interop.Outlook.Inspector) _
    Handles tyINS.NewInspector

    tyAI = Inspector.CurrentItem
    If tyAI.MessageClass = "IPM.Appointment" Then
      Dim f As New TyApptItem(tyAI)
      f.ol = Me
      f.Show()
    Else

    End If
  End Sub

The event utilizes the passed Inspector object and assigns it to the tyAI variable. This is important as it allows us to code against this Inspector's Open event (discussed next). We only want to respond to appointment items, so we check the MessageClass property of the Inspector to determine if it is an appointment. If so, we create and show a new instance of the add-in's custom appointment form. While opening the form, we also pass a reference to the opened appointment item (tyAI) as well as a reference to Outlook (Me). Both of these objects are required by the custom form and will be explained in Step 3.

The tyAI_Open Event
The NewInspector event displays the TyApptItem form, but it does not prevent the newly created Inspector object from displaying. To complete the switch, all that is required is one line of code inside the tyAI variable. Remember, this variable contains a reference to the CurrentItem of the active Inspector.


  Private Sub tyAI_Open(ByRef Cancel As Boolean) Handles tyAI.Open
    Cancel = True
  End Sub

Setting Cancel equal to True prevents Outlook from opening the default appointment form and allows the custom TyApptItem to take the reins of the user's calendar experience.

Step 3: Code the Custom Appointment Form (TyApptItem.vb)
In Step 1, I showed you how to design a custom WinForm that will replace the default Outlook appointment form. In Step 2, I explained the code required to prevent Outlook's appointment form from opening and to display the add-in's appointment form in its place. In this step, I will cover the code required to turn the TyApptItem form from just another pretty face into something truly useful.

I will cover the different methods and events according the form's workflow. Add the following namespace directives above the form's class definition:

  Imports Outlook = Microsoft.Office.Interop.Outlook
  Imports Office = Microsoft.Office.Core
  Imports System.Xml

Inside the class definition, insert the following variable declarations:

  Friend ol As Outlook.Application
  Private ai As Outlook.AppointmentItem

These two variables will store references to Outlook and to the form's related Outlook appointment item respectively.

New
The New method accepts an Outlook appointment item as a parameter. The appointment is needed by the form in order to read and write appointment data to the default Calendar folder.

  Friend Sub New(ByVal Appointment As Outlook.AppointmentItem)
    InitializeComponent()
    ai = Appointment
    OpenAppointment()
  End Sub

After storing a local reference to the passed appointment item, the procedure calls the OpenAppointment method.

TyApptItem_Load
Every time the form displays to the user, tscboProjects must be filled with a listing of available projects. The form's Load event calls the LoadProjects method.

  Private Sub TyApptItem_Load(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Me.Load

    LoadProjects()
  End Sub

LoadProjects
The LoadProjects method takes care of filling the tscboProjects combo box with items found in the solution's project file—Projects.xml. This XML file contains a listing of all active projects and is an easy way to demonstrate how the dynamic nature of the form's menu. You could, with a just a bit more code, utilize a Web service that publishes the project data or access a database directly.

  Private Sub LoadProjects()
     'This is hard coded for convenience.
    'Be sure to change the file location to match the location on your system.
    Dim xtr As New _
     XmlTextReader("E:\Articles\Devx05\Code\Devx05\Projects.xml") 

    Do While xtr.Read
      Select Case xtr.NodeType
        Case XmlNodeType.Element
          If xtr.Name = "project" Then
            xtr.Read()
            tscboProjects.Items.Add(xtr.Value.ToString)
          End If

        Case Else
      End Select
    Loop

    xtr.Close()

  End Sub

The method opens the Projects.xml file found in the application's startup path. Once the file is opened, the data is read and added to the combo box's Items collection. These values can then be selected from the TyApptItem form to assign a project to the time entry record.

SaveAppointment
The SaveAppointment method takes the information entered into the TyApptItem form and saves it as an Outlook appointment item in the default calendar folder. The method accesses the default calendar folder and then copies the data from the TyApptItem to the form's referenced AppointmentItem (ai), which serves as the storage object for our custom form.

  Private Sub SaveAppointment()
    Dim apptFolder As Outlook.MAPIFolder = _
      ol.GetNamespace("MAPI").GetDefaultFolder _
      (Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar)
    Dim up As Outlook.UserProperty

    ai.Subject = Me.txtSubject.Text
    ai.Start = CDate(Format(Me.dtpStartDate.Value, "Short Date") & " " & _
      Format(Me.dtpStartTime.Value, "t"))
    ai.End = CDate(Format(Me.dtpDueDate.Value, "Short Date") & " " & _
      Format(Me.dtpDueTime.Value, "t"))
    ai.Body = Me.txtBody.Text


    'Look for the custom project property
    up = ai.UserProperties.Find("TyProject")
    If IsNothing(up) Then
      up = ai.UserProperties.Add("TyProject", Outlook.OlUserPropertyType.olText)
      up.Value = Me.tscboProjects.SelectedItem
    Else
      up.Value = Me.tscboProjects.SelectedItem
    End If

    ai.Save()

End Sub

A key part of this method is contained in the last chunk of code. This portion checks for the existence of a user-defined field named TyProject. This field must be added to all new items at the time they are saved in order to preserve the project value selected in tscboProjects (this field will be added to the default calendar folder in Step 4). Although the field exists in the folder, it has to be added to the AppointmentItem manually (Outlook does not do it automatically—at least in my testing). A quick test is performed to check for the existence of the TyProject field. If the property does not exist for this item, it's added and the selected project value is inserted. If it already exists then the method inserts the project value. Once the AppointmentItem receives all data, we save the item and now have an appointment record.

OpenAppointment
Saving the appointment is only half the battle. What happens when the user attempts to open an appointment item? Well there are two possibilities. Either they are attempting to open an existing appointment, or they are attempting to create a new one. In the former case, we need to read the data from the saved appointment item and read it into the custom TyApptItem form instance. In the latter case we can skip reading data as none exists and stick with only creating an instance to the TyApptItem form.

The OpenAppointment method handles both scenarios as follows:


  Private Sub OpenAppointment()
    If Not IsNothing(ai.EntryID) Then
      Me.txtSubject.Text = ai.Subject
      Me.dtpStartDate.Value = ai.Start
      Me.dtpStartTime.Value = ai.Start
      Me.dtpDueDate.Value = ai.End
      Me.dtpDueTime.Value = ai.End
      Me.txtBody.Text = ai.Body
      Dim up As Outlook.UserProperty = ai.UserProperties.Find("TyProject")
      If Not IsNothing(up) Then
        Me.tscboProjects.Text = up.Value
      End If
    End If
  End Sub

Determine whether it is an existing appointment by checking the EntryID property of form's AppointmentItem (ai). If the item has an EntryID (which is the item's unique identifier within the Outlook data store), then it is an existing item and we can proceed to read its data into

TyApptItem.

tsbSaveAndClose_Click
The tsbSaveAndClose button calls the SaveAppointment method and closes the form.

  Private Sub tsbSave_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles tsbSaveandClose.Click

    SaveAppointment()
    Me.Close()
  End Sub

tsbSave_Click

The tsbSave button calls the SaveAppointment method and leaves the form open.

Private Sub tsbSave_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles tsbSave.Click SaveAppointment() End Sub

tsbDelete_Click
The Delete button deletes the current appointment item by calling the Delete method of the referenced appointment item. Once deleted, the method closes the open instance of the TyApptItem form.

Private Sub tsbDelete_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles tsbDelete.Click

    ai.Delete()
    Me.Close()
  End Sub

Step 4: Miscellaneous Setup Issues

Add User-Defined property
The form requires that user-defined fields exist in Outlook's default Calendar folder named TyProject. To add this field:

  1. Navigate to the default Calendar folder.
  2. From the Outlook menu, select View > Arrange By > Current View > Events.
  3. Right-Click Subject column and select Field Chooser from the context menu.
  4. Click the New button to display the New Field dialog box.
  5. Enter TyProject in the Name field. Leave the Type and Format fields as Text.
  6. Click OK.
    This field will store the value selected from the tscboProjects control.

Projects.xml
The project depends on the existence of an XML file residing in the application's startup path. This file is named Projects.xml and has simple schema to describe active projects. Insert an XML file into the project (Project > Add New Item > XML File) and name it Projects.xml. Insert the following text as the file's contents:

<?xml version="1.0" encoding="utf-8" ?>
<projects>
  <project>Accounting</project>
  <project>Consulting</project>
  <project>Sales and Marketing</project>
  <project>Project Management</project>
  <project>Development</project>
  <project>Testing</project>
</projects>

As previously discussed, this file is utilized by the LoadProjects method located in the TyApptItem form.

Test the Solution
Press F5 to test the solution. Once Outlook opens, navigate to the default calendar folder and open a new appointment by double-clicking in the calendar pane.

  • Did the custom appointment form open instead of Outlook's default appointment form?
  • Go ahead and add some data and save the form. Do you see the new appointment item added to the calendar just like any other appointment?
  • Now open the newly created appointment. Did the custom display and populate with the correct data?

Outlook is powerful platform for building custom applications and can be customized to fit your solution's needs. As this article demonstrated, you don't even have to utilize the collection of forms provided by Outlook if they do not suit the needs of your solution. This strategy for building custom GUIs within Outlook opens up all kinds of new possibilities for your Outlook-based solutions.

   
Ty Anderson runs Cogent Company, a consultancy in Dallas specializing in leveraging technology to enable business strategy. Ty is a regular contributor to the Microsoft Developer Network (MSDN) and has recently written a book, Office Programming 2003: Real World Applications, focused entirely on building applications with the Microsoft Office System 2003.
Submit article to:
Extending your solution to run on Microsoft technology is easier than ever. Through NXT, you can reach more customers, increase revenues and slash development time and costs, accelerating both your time to market and profitability. Get the details on NTX. >>
Sign up for your free e-mail newsletters today!
DevX Windows Developer Update

More Newsletters
Using the New ListView Control in ASP.NET 3.5
SMS Messaging Using the .NET Compact Framework
Debugging SQL Server Stored Procedures Through Visual Studio.NET
Design and Use of Moveable and Resizable Graphics, Part 2
The Bakers Dozen: 13 Tips for Building Database Web Applications Using ASP.NET 3.5, LINQ, and SQL Server 2005 Reporting Services



JupiterOnlineMedia

internet.com earthweb.com Devx.com mediabistro.com Graphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info

Copyright 2008 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Web Hosting | Newsletters | Tech Jobs | Shopping | E-mail Offers