Customizing Outlook Reading pane
To show you how easily you can implement Outlook regions, we'll create two different view regions:
- Outlook Navigation Pane region that displays a list of recently received emails, please look through
this project first if you haven't seen it yet
- Outlook Reading pane region that shows address details for the sender of the current message, it is described further on this page
Start Visual Studio and create a new Outlook Add-in Project:
Top Reading Pane region: address details
This region will be displayed prominently above the e-mail header in the Outlook Reading Pane and will show address details for the sender
of the current message. If the user has sent the e-mail from an Internet/POP3 or other non-Exchange account, AND they have a related
Contact item in one of your Contact folders (that is address book enabled), then it will show all three of their e-mail addresses
(if they have three!) plus their mailing address. For senders from your Exchange organization, it will only show their primary e-mail
address and address details pulled from their Global Address List (GAL) entry. We'll also add some smart functionality so that if there
is no related Contact or GAL item, we'll collapse the region so as not to overly bother the user with empty controls.
Building the Outlook Reading Pane region
Once again, we need to add another new Region form to the project with the New Region Wizard: launch the Add New Item dialog and
select "ADX Region for Outlook and VSTO":
Select ReadingPane.Top for the Explorer Layout, check MailItem for Explorer Item Types, and then click Next. Click Next again in the next
step of the Wizard which is for Inspector regions only, until you get to the final screen:
For the Address Details form, we want it to start Minimized, so select that value for the Default region state. Also clear the "Allow
the hidden state" checkbox, check the "Always show header" checkbox, and click Finish.
Next, we need to design the UI of our custom form. Simply add the following controls to ADXOlForm2:
- Four Label controls
- Three TextBox controls ("txtEmail1", "txtEmail2", "txtEmail3")
- A fourth TextBox control ("txtMailingAddress") with Multiline set to True
The layout should look like this in the designer:
Then add the code below to the class. In summary, the code will:
- Monitor the ADXSelectionChange event which will fire every time an e-mail is selected in the current folder
- Use the Outlook.Explorer.Selection object to detect what is selected and only process single selections of e-mail item types only
- Retrieve an Outlook.MailItem object from the Selection object
- Obtain an Outlook.AddressEntry object from the MailItem.Sender property
- Process e-mail and address information differently for populating the controls, based on whether the sender is from an Internet
account (e.g. POP3 or IMAP) or an Exchange user in the same Exchange Organization
- If the sender is from the Internet, call the AddressEntry.GetContact method to retrieve a related ContactItem object if an associated Contact
item exists for the sender in one of the user's Contacts folders. If it does, use the ContactItem.EmailAddress1 (and EmailAddress2,
and EmailAddress3) and ContactItem.MailingAddress properties to populate the controls)
- If the sender is an Exchange user, call AddressEntry.GetExchangeUser to retrieve an Outlook.ExchangeUser object (which maps to the
user's entry in the Global Address List in Exchange). Then use the ExchangeUser.PrimarySmtpAddress property to populate only the
"txtEmail1" TextBox control (the user will not have multiple e-mails unless they have other aliases, which we won't handle).
Also concatenate the values of the ExchangeUser.StreetAddress, ExchangeUser.City, ExchangeUser.StateOrProvince and ExchangeUser.PostalCode
property values for passing to the txtMailingAddress TextBox control, as there is no MailingAddress property equivalent in an ExchangeUser
object like there is for a ContactItem object.
- Collapse or expand the form region as appropriate (set Me.RegionState to AddinExpress.OL.ADXRegionState.Normal or
AddinExpress.OL.ADXRegionState.Minimized) if there is no address details for the selected item (or for non-email item types)
VB.NET
Private Sub ADXOlForm2_ADXSelectionChange() Handles Me.ADXSelectionChange
Dim objAE As Outlook.AddressEntry = Nothing
Dim objSelection As Outlook.Selection = Nothing
Dim objExplorer As Outlook.Explorer
objExplorer = TryCast(ExplorerObj, Outlook.Explorer)
Try
'Exception could occur when selecting root folder of store
objSelection = objExplorer.Selection
Catch ex As System.Exception
'Ignore; NULL check below will branch out
End Try
'Clear the controls and minimize the form
txtEmail1.Text = ""
txtEmail2.Text = ""
txtEmail3.Text = ""
txtMailingAddress.Text = ""
If objSelection Is Nothing Then
Me.RegionState = AddinExpress.OL.ADXRegionState.Minimized
Exit Sub
End If
If objSelection.Count = 1 Then
Dim objItem As Object
Dim objMail As Outlook.MailItem
objItem = objSelection.Item(1)
If objItem.Class = Outlook.OlObjectClass.olMail Then
objMail = TryCast(objItem, Outlook.MailItem)
If Not objMail Is Nothing Then
Try
'Warning: slow Outlook Anywhere connections could cause a
'problem with this call
objAE = objMail.Sender
Catch ex As System.Exception
System.Windows.Forms.MessageBox.Show(ex.ToString)
Me.RegionState = AddinExpress.OL.ADXRegionState.Hidden
GoTo Release1
End Try
If objAE Is Nothing Then
Me.RegionState = AddinExpress.OL.ADXRegionState.Hidden
GoTo Release1
End If
Select Case objAE.AddressEntryUserType
Case Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry
Dim objEU As Outlook.ExchangeUser
objEU = objAE.GetExchangeUser
If Not objEU Is Nothing Then
txtEmail1.Text = objEU.PrimarySmtpAddress
txtEmail2.Text = "N/A"
txtEmail3.Text = "N/A"
txtMailingAddress.Text = objEU.StreetAddress & vbCrLf & _
objEU.City & ", " & objEU.StateOrProvince & " " & _
objEU.PostalCode
Marshal.ReleaseComObject(objEU)
objEU = Nothing
End If
'Raise the Region!
Me.RegionState = AddinExpress.OL.ADXRegionState.Normal
Case Outlook.OlAddressEntryUserType.olSmtpAddressEntry
Dim objContact As Outlook.ContactItem
objContact = objAE.GetContact
If Not objContact Is Nothing Then
txtEmail1.Text = objContact.Email1Address
txtEmail2.Text = objContact.Email2Address
txtEmail3.Text = objContact.Email3Address
txtMailingAddress.Text = objContact.MailingAddress
Marshal.ReleaseComObject(objContact) : objContact = Nothing
'Raise the Region!
Me.RegionState = AddinExpress.OL.ADXRegionState.Normal
Else
Me.RegionState = AddinExpress.OL.ADXRegionState.Minimized
End If
Case Else
Me.RegionState = AddinExpress.OL.ADXRegionState.Minimized
End Select
Release1:
objMail = Nothing
If Not objAE Is Nothing Then
Marshal.ReleaseComObject(objAE) : objAE = Nothing
End If
End If
Else
Me.RegionState = AddinExpress.OL.ADXRegionState.Minimized
End If
Marshal.ReleaseComObject(objItem) : objItem = Nothing
Else
Me.RegionState = AddinExpress.OL.ADXRegionState.Minimized
End If
Marshal.ReleaseComObject(objSelection) : objSelection = Nothing
End Sub
C#
private void ADXOlForm2_ADXSelectionChange()
{
Outlook.AddressEntry objAE = null;
Outlook.Selection objSelection = null;
Outlook.Explorer objExplorer = default(Outlook.Explorer);
objExplorer = ExplorerObj as Outlook.Explorer;
try
{
//Exception could occur when selecting root folder of store
objSelection = objExplorer.Selection;
}
catch (System.Exception ex)
{
//Ignore; NULL check below will branch out
}
//Clear the controls and minimize the form
txtEmail1.Text = "";
txtEmail2.Text = "";
txtEmail3.Text = "";
txtMailingAddress.Text = "";
if (objSelection == null)
{
this.RegionState = AddinExpress.OL.ADXRegionState.Minimized;
return;
}
if (objSelection.Count == 1)
{
Outlook.MailItem objMail = default(Outlook.MailItem);
try
{
objMail = objSelection[1];
}
catch (Exception ex)
{
this.RegionState = AddinExpress.OL.ADXRegionState.Hidden;
return;
}
if ((objMail != null))
{
try
{
//Warning: slow Outlook Anywhere connections could cause a
//problem with this call
objAE = objMail.Sender;
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.ToString());
this.RegionState = AddinExpress.OL.ADXRegionState.Hidden;
goto Release1;
}
if (objAE == null)
{
this.RegionState = AddinExpress.OL.ADXRegionState.Hidden;
goto Release1;
}
switch (objAE.AddressEntryUserType)
{
case Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry:
Outlook.ExchangeUser objEU = default(Outlook.ExchangeUser);
objEU = objAE.GetExchangeUser();
if ((objEU != null))
{
txtEmail1.Text = objEU.PrimarySmtpAddress;
txtEmail2.Text = "N/A";
txtEmail3.Text = "N/A";
txtMailingAddress.Text = objEU.StreetAddress +
Environment.NewLine +
objEU.City + ", " +
objEU.StateOrProvince + " " +
objEU.PostalCode;
Marshal.ReleaseComObject(objEU);
objEU = null;
}
//Raise the Region!
this.RegionState = AddinExpress.OL.ADXRegionState.Normal;
break;
case Outlook.OlAddressEntryUserType.olSmtpAddressEntry:
Outlook.ContactItem objContact = default(Outlook.ContactItem);
objContact = objAE.GetContact();
if ((objContact != null))
{
txtEmail1.Text = objContact.Email1Address;
txtEmail2.Text = objContact.Email2Address;
txtEmail3.Text = objContact.Email3Address;
txtMailingAddress.Text = objContact.MailingAddress;
Marshal.ReleaseComObject(objContact);
objContact = null;
//Raise the Region!
this.RegionState = AddinExpress.OL.ADXRegionState.Normal;
}
else
{
this.RegionState = AddinExpress.OL.ADXRegionState.Minimized;
}
break;
default:
this.RegionState = AddinExpress.OL.ADXRegionState.Minimized;
break;
}
Release1:
Marshal.ReleaseComObject(objMail);
objMail = null;
if ((objAE != null))
{
Marshal.ReleaseComObject(objAE);
objAE = null;
}
}
}
else
{
this.RegionState = AddinExpress.OL.ADXRegionState.Minimized;
}
Marshal.ReleaseComObject(objSelection);
objSelection = null;
}
Design your custom forms and let Advanced Regions do the rest!
That is all that is required for two simple Outlook view regions for Reading pane and Navigation pane.
The key thing to remember is that the New Region Wizard does all of the hard work for you.
The code that is needed for implementing the region and ensuring that the regions load in the contexts you configured are automatically created.
You just need to design your forms and use the provided events and exposed Outlook objects in the forms derived from the AddinExpress.OL.ADXOlForm class,
or easily access your regions from the ThisAddin class, to build your final solution.
|