Eric's Blog

Day to day experience in .NET
Welcome to Blogs @ IRM Sign in | Join | Help
 Search

Disclaimer

The content of this site is my own personal opinion and does not in any way represent my employer, it's subsideries or affiliates. These postings are provided "AS IS" with no warranties, and confer no rights.

This Blog

Adding a Property Page to Outlook 2007 Options Dialog

Last week I promised to blog a little about my experience to do an add-in for Outlook 2007. In this post I will show an example of how to add a property page to the Options dialog. The result looks something like this (in swedish):

Outlook 2007 Property Page
The first thing to do is to catch the OptionsPagesAdd event of the Application object. This event should be set up in the ThisAddIn_Startup event that is part of the ThisAddIn class that VSTO 2 SE creates when you start a new Outlook add-in project.

//Option dialog
this.Application.OptionsPagesAdd += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_OptionsPagesAddEventHandler(Application_OptionsPagesAdd);
void Application_OptionsPagesAdd(Microsoft.Office.Interop.Outlook.PropertyPages Pages)
{
    OptionsPropertyPage page = new OptionsPropertyPage(this);
    Pages.Add(page, page.Text);
}

In the event you are supposed to add your property pages to the Pages collection that you receive as an argument. The property pages must implement the Microsoft.Office.Interop.Outlook.PropertyPage interface. I have created an base class for all property pages as an user control that implements the interface and provides some other useful features.
[System.Runtime.InteropServices.ComVisible(true)]
public partial class PropertyPageBase : UserControl, MSOutlook.PropertyPage
{
    private MSOutlook.PropertyPageSite site;
    private bool isDirty;
    public PropertyPageBase()
    {
        InitializeComponent();
    }
    protected virtual void OnApply() { if (IsDirty) MessageBox.Show("Override OnApply!"); }
    protected override void OnLoad(EventArgs e)
    {
        Type type = typeof(UserControl);
        Type oleType = type.Assembly.GetType("System.Windows.Forms.UnsafeNativeMethods+IOleObject");
        if (oleType == null) thrownewInvalidOperationException("Could not get 'System.Windows.Forms.UnsafeNativeMethods+IOleObject'.");
        System.Reflection.MethodInfo method = oleType.GetMethod("GetClientSite");
        if (method == null) thrownewInvalidOperationException("Could not get method 'IOleObject.GetClientSite'.");
        site = method.Invoke(this, null) as MSOutlook.PropertyPageSite;
        base.OnLoad(e);
    }
    [Browsable(false)]
    public bool IsDirty
    {
        get { return isDirty; }
        set
        {
            if (isDirty != value)
            {
                isDirty = value;
                if (site != null) site.OnStatusChange();
            }
        }
    }
    #region PropertyPage Members
    public void Apply()
    {
        OnApply();
        this.isDirty = false;
    }
    bool MSOutlook.PropertyPage.Dirty
    {
        get { returnthis.IsDirty; }
    }
    public virtual void GetPageInfo(refstring HelpFile, refint HelpContext)
    {
    }
    #endregion
}

Worth noting in the class above is that it of course must be visible to COM which is set by the ComVisible attribute of the class. There is a hack in the OnLoad that I found here, which is also a complete property page sample. You need the site to be able to force Outlook to call the IsDirty property of the PropertyPage interface and if you return true from the property it will enable the Apply-button.
In the inheriting class you are supposed to set the IsDirty property when something changes and override the OnApply method to do your own saving. In my case I write the settings to a file in the users roaming profile.
Published den 22 december 2006 12:21 by ericqu
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Erics Blog said:

This post will continue my exploration of programming Outlook 2007, by showing how to get information

januari 31, 2007 11:10
 

Ryan Gregg said:

I noticed that your tab background doesn't fill with a gradient like the other tabs in the dialog use. You can use the VisualStyleRenderer class in System.Windows.Forms to paint this background as part of your OnPaint event, and then use controls with transparent backgrounds to accomplish the rest.
februari 13, 2007 21:38
 

ericqu said:

Thanks for the tip. It looks much better now :-)

februari 14, 2007 21:55
 

Dennis said:

Hi Eric, I noticed you have a button which would load a dialog box (... button), I also have the same button but everytime I process a call to the Show method of the form, Outlook just suddenly hangs... Why is this so? Thank you
februari 21, 2008 03:15
 

ericqu said:

I don't know. I use ShowDialog which is more natural in my situation, because the user needs to finish that dialog before continuing working in the Options dialog.

februari 21, 2008 22:20
 

Dennis said:

Hi Ericqu, Thank you for responding. Just another question for that particular button click event, did you add anything special? I tried copying your OnLoad event function to check if my OnLoad is the problem but it still did not work. I tried launching SelectNamesDialog window and outlook just hangs even if I just use a MessageBox inside the button click event it hangs. Would you mind sharing your button click event? Thank you again in advance.
februari 22, 2008 04:39
 

ericqu said:

Here is one example of how I open child dialogs:

using (ProjectProperties form = new ProjectProperties())

{

   if (form.ShowDialog() == DialogResult.OK)

   {

       ...

       this.IsDirty = true;

   }

}

februari 22, 2008 15:56
 

Milad said:

thanks for this post.
september 24, 2008 11:36
 

Milad said:

thanks for this post. but How to save and retrieve data entered in the Custom PropertyPage ?
september 24, 2008 11:44
 

ericqu said:

I store the projects from the PropertyPage as a file (on disc) in the users profile (if I remember correct, I use the roaming profile).

september 25, 2008 20:13
 

Andrey said:

Hi Ericqu, Great post. Very helpful. Can you tell how to draw background with VisualStyleRenderer? Thanks
oktober 14, 2008 01:20
 

ericqu said:

protected override void OnPaint(PaintEventArgs e)

{

   base.OnPaint(e);

   System.Windows.Forms.VisualStyles.VisualStyleRenderer renderer = new System.Windows.Forms.VisualStyles.VisualStyleRenderer(System.Windows.Forms.VisualStyles.VisualStyleElement.Tab.Body.Normal);

   renderer.DrawBackground(e.Graphics, this.Bounds, e.ClipRectangle);

}

oktober 14, 2008 21:56
 

Andrey said:

Fantastic. Thank you. P.S. May be it make sense create VisualStyleRenderer object once in OnLoad and use it all the time, instead of creating it every time in OnPaint.
oktober 20, 2008 10:19
 

ericqu said:

It might be better to do as you suggest. Haven't had any reason to optimize this code. :)

oktober 20, 2008 11:14
 

Gleedo said:

When you create the UserControl OptionsPropertyPage which inherits from PropertyPageBase, what should the usercontrols argument in it's constructor be set to? You pass in 'this'. I don't have that constructor argument so this is perhaps why my property page is not showing. Any help appreciated.
april 14, 2010 16:02
 

ericqu said:

It is not necessary to take any argument in the constructor for your user control. The fact that I use this as an argument to the property page user control is specific to my business logic and not for any logic associated with showing the property page.

All that should be needed is to inherit from the class above in you user control and handle the OptionsPageAdd event as described.

april 14, 2010 21:03
 

Hemant Sharma said:

[Gleedo] have you added [System.Runtime.InteropServices.ComVisible(true)] attribute to your usercontrol class(as described by ericqu), because in my case also it was not showing the tab and after adding this attribute to my usercontrol class it is showing.
juni 14, 2010 17:14

Leave a Comment

(required) 
(optional)
(required) 
Submit
Powered by Community Server, by Telligent Systems