Microsoft Outlook アドイン のプロパティシート（アドイン オプション）を作成する

#説明
Visual Studio 2013 以降で Microsoft Outlook アドインのプロパティシート（アドイン オプション）を作成する方法の簡単な説明です。
ThisAddIn クラスの [Startup](https://msdn.microsoft.com/ja-jp/library/office/ff869298.aspx) イベントで [Application](https://msdn.microsoft.com/ja-jp/library/office/ff863377.aspx) オブジェクトの [OptionsPagesAdd](https://msdn.microsoft.com/ja-jp/library/office/ff868446.aspx) イベントハンドラを登録し、そのハンドラのなかで後述のプロパティページを追加します。
プロパティページは、ユーザーコントロールから作成します。ユーザーコントロール上に希望するコントロールを追加し、さらに Microsoft.Office.Interop.Outlook.[PropertyPage](https://msdn.microsoft.com/ja-jp/library/microsoft.office.interop.outlook.propertypage.aspx) インターフェイスを実装します。
プロパティページの項目が編集されたら、[IOleObject.GetClientSite](https://msdn.microsoft.com/ja-jp/library/windows/desktop/ms692603.aspx) メソッドで得た通知先（ClientSite？）が Microsoft.Office.Interop.Outlook.[PropertyPageSite](https://msdn.microsoft.com/ja-jp/library/microsoft.office.interop.outlook.propertypagesite.aspx) インターフェイスを実装しているはずなので、これの [OnStatusChange](https://msdn.microsoft.com/ja-jp/library/microsoft.office.interop.outlook.propertypagesite.onstatuschange.aspx) メソッドを呼び出して通知します。
（VBA などのサンプルコードでは、通知先サイトをユーザーコントロールの Parent プロパティからキャストして取れるように書かれていたりする場合もありますが（それができると至極簡単なのですが）、.NET では勝手が違うようです（null になってしまいます。理由をご存知な方、ぜひ教えてください））

#コード
```C#
// Outlook:ThisAddin.cs

    public partial class ThisAddIn
    {
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            Application.ItemSend += Application_ItemSend;
            Application.OptionsPagesAdd += Application_OptionsPagesAdd;
        }

        void Application_OptionsPagesAdd(Outlook.PropertyPages Pages)
        {
            Pages.Add(new MyPropPage(), "General");
            // 複数ページあれば、さらに Add します。
        }

        // .... ほかのコードがあれば続行
    }

// MyPropPage.cs : 「ユーザーコントロール」をテンプレートにプロパティページを作成します。COM 参照可能なよう ComVisible(true) 属性をつけ、Microsoft.Office.Interop.Outlook.PropertyPage インターフェイスを組み込みます。

    [System.Runtime.InteropServices.ComVisible(true)]
    public partial class MyPropPage : UserControl , Microsoft.Office.Interop.Outlook.PropertyPage
    {
        private Microsoft.Office.Interop.Outlook.PropertyPageSite _propertyPageSite;

        public MyPropPage()
        {
            InitializeComponent();

            //「設定 (Settings)」に UserName（String 型）を記憶させ、プロパティシート上の textBoxUserName（テキストボックス）で変更を扱う場合
            textBoxUserName.Text = Properties.Settings.Default.UserName;
            textBoxUserName.TextChanged += (sender, e) =>
            {
                // テキストボックスが編集されたら、OnStatusChange メソッドで通知します。
                if (_propertyPageSite != null)
                    _propertyPageSite.OnStatusChange();
            };
        }

        protected override void OnLoad(EventArgs e)
        {
            // プロパティ変更の通知先を得ます
            // => リフレクションを利用して .NET ライブラリ中の System.Windows.Forms.UnsafeNativeMethods.IOleObject クラスにある GetClientSite メソッドを呼び出します。
            Type type = typeof(System.Object);
            string assembly = type.Assembly.CodeBase.Replace("mscorlib.dll", "System.Windows.Forms.dll");
            assembly = assembly.Replace("file:///", "");
 
            string assemblyName = System.Reflection.AssemblyName.GetAssemblyName(assembly).FullName;
            Type unsafeNativeMethods = Type.GetType(System.Reflection.Assembly.CreateQualifiedName(assemblyName, "System.Windows.Forms.UnsafeNativeMethods"));
 
            Type oleObj = unsafeNativeMethods.GetNestedType("IOleObject");
            System.Reflection.MethodInfo methodInfo = oleObj.GetMethod("GetClientSite");
            _propertyPageSite = methodInfo.Invoke(this, null) as Microsoft.Office.Interop.Outlook.PropertyPageSite;
        }

        public void Apply()
        {
            // OK や 適用ボタンをクリックされたときの処理を記述します。
            Properties.Settings.Default.UserName = textBoxUserName.Text;
            Properties.Settings.Default.Save();
        }

        public bool Dirty
        {
            get {
                // 適用ボタンを有効にしたい状態の場合は true を返すようにします。ここでは、「設定」の記憶値とテキストボックスの値が異なっている場合に true を返すようにしています。
                return (textBoxUserName.Text != Properties.Settings.Default.UserName);
            }
        }

        public void GetPageInfo(ref string HelpFile, ref int HelpContext)
        {
            // ヘルプファイル (.chm) を指定できるようです。不要なら何も書かないでよいです。
        }

        // .... ほかのコードがあれば
    }

```
#Tips
- ユーザーコントロールのサイズは、デザイン時のままではなく表示されるプロパティシートのサイズに合わせられます。ゆえに、ユーザーコントロール上に配置される各コントロールの Anchor や Dock プロパティに任意の値を指定することで、プロパティシート上でフィットした位置やサイズに調整できます。


#参考にしたサイト
- [Adding Custom Property Pages (MSDN)](https://msdn.microsoft.com/en-us/library/office/ff864286.aspx)
- [Customize Outlook "options" dialog (MSDN)](https://social.msdn.microsoft.com/Forums/vstudio/en-US/f7dd6f82-13e7-4a28-8316-9c535eaa7518/customize-outlook-options-dialog?forum=vsto#c45f5fb1-c15d-4a5e-bf0e-7cb677462fdd)
- [How to implement OL PropertyPage with c# (OutlookCode(TM)) ](http://www.outlookcode.com/codedetail.aspx?id=978)
- [Get Outlook.PropertyPageSite so you can call OnStatusChange() and update UI (StackOverflow)](http://stackoverflow.com/questions/21123982/get-outlook-propertypagesite-so-you-can-call-onstatuschange-and-update-ui)
- [Unable to display propertypage in outlook 2010 (Office DevCenter)](https://social.msdn.microsoft.com/Forums/office/en-US/4ff82048-cee1-42dc-b5e7-208c9a640ad4/unable-to-display-propertypage-in-outlook-2010/)
- [Outlook AddIn 'PropertyPage' not showing up in Outlook Options (StackOverflow)](http://stackoverflow.com/questions/28930745/outlook-addin-propertypage-not-showing-up-in-outlook-options)
- [PropertyPage.GetPageInfo メソッド (MSDN 機械翻訳)](https://msdn.microsoft.com/ja-jp/library/office/ff863621.aspx)
- [VSTO アドインのプログラミング (MSDN)](https://msdn.microsoft.com/ja-jp/library/bb157876.aspx)