WinForms向け、(安全に)画面描画を抑制するためのサンプル

#はじめに
コントロールの描画を一時的に止めたい場合、該当する（一番上の）コントロールへ WM_SETREDRAW メッセージを送ることで制御できます。
.NET Framework で Windows Forms 上の描画をコントロールするクラスを作ってみました。
※2019/3/12 Form に特化したクラスを追加

#コード
[using](https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/using-statement) ステートメントを利用する仕組みで、解除漏れを防いでいます。

```C#:Program.cs
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            using (var sus = new RedrawSuspension(this.Handle))
            {
                // このなかでフォームの描画が抑制されます

            }
            this.Refresh(); // これを忘れると抑制解除したあとで描画が行われません
        }

        // ※2019/3/12 追加：こちらのほうがより安全
        private void button2_Click(object sender, EventArgs e)
        {
            using (var sus = new FormRedrawSuspension(this))
            {
                // このなかでフォームの描画が抑制されます

            }
            // 抜けるとき（FormRedrawSuspensionオブジェクトがDisposeされるとき）に、フォームがRefreshされます。
        }

        /// <summary>
        /// ※こちらは初代：FormRedrawSuspension のほうをおすすめします
        /// コントロールの画面描画抑制を制御するオブジェクトを提供します。
        /// </summary>
        private class RedrawSuspension : IDisposable
        {
            private IntPtr _hWnd;

            /// <summary>
            /// オブジェクトを構築し、画面描画を抑制します。オブジェクトを破棄すると画面描画抑制が解除されます。
            /// </summary>
            /// <param name="hWnd">ウインドウハンドル</param>
            public RedrawSuspension(IntPtr hWnd)
            {
                _hWnd = hWnd;
                SendSetRedrawMessage(false);
            }

            /// <summary>
            /// 画面描画抑制を解除して、オブジェクトを破棄します。
            /// </summary>
            public void Dispose()
            {
                SendSetRedrawMessage(true);
            }

            private void SendSetRedrawMessage(bool enableRedraw)
            {
                NativeMethods.SendMessage(_hWnd, NativeMethods.WM_SETREDRAW, enableRedraw ? new IntPtr(1) : IntPtr.Zero, IntPtr.Zero);
            }

            private class NativeMethods
            {
                // https://docs.microsoft.com/ja-jp/visualstudio/code-quality/ca1060-move-p-invokes-to-nativemethods-class
                private NativeMethods() { }

                [DllImport("user32.dll")]
                internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 dwMsg, IntPtr wParam, IntPtr lParam);

                internal const UInt32 WM_SETREDRAW = 11;
            }
        }

        /// <summary>
        /// ※2019/3/12 追加
        /// フォームの画面描画抑制を制御するオブジェクトを提供します。
        /// </summary>
        internal class FormRedrawSuspension : IDisposable
        {
            private System.Windows.Forms.Form _form;

            /// <summary>
            /// オブジェクトを構築し、画面描画を抑制します。オブジェクトを破棄すると画面描画抑制が解除されます。
            /// </summary>
            /// <param name="form">制御するフォーム</param>
            public FormRedrawSuspension(System.Windows.Forms.Form form)
            {
                _form = form;
                SendSetRedrawMessage(false);
            }

            /// <summary>
            /// 画面描画抑制を解除してフォームを再描画させ、オブジェクトを破棄します。
            /// </summary>
            public void Dispose()
            {
                SendSetRedrawMessage(true);
                _form.Refresh();
            }

            private void SendSetRedrawMessage(bool enableRedraw)
            {
                NativeMethods.SendMessage(_form.Handle, NativeMethods.WM_SETREDRAW, enableRedraw ? new IntPtr(1) : IntPtr.Zero, IntPtr.Zero);
            }

            private class NativeMethods
            {
                // https://docs.microsoft.com/ja-jp/visualstudio/code-quality/ca1060-move-p-invokes-to-nativemethods-class
                private NativeMethods() { }

                [DllImport("user32.dll")]
                internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 dwMsg, IntPtr wParam, IntPtr lParam);

                internal const UInt32 WM_SETREDRAW = 11;
            }
        }
    }
}

```

#使い方
コードにも載せましたが、FormRedrawSuspension（またはRedrawSuspension） クラスのオブジェクトを using ステートメントで括って生成させると、usingステートメント内では描画が抑制され、抜け出す（＝オブジェクトを破棄する）ときに描画抑制が解除されます。FormRedrawSuspensionクラスの場合は、抜け出すときにフォームの再描画も自動で行われます。