【C#/WinForms】MDIの子フォームの表示時のチラツキをなくす方法

この記事は約4分で読めます。

自作エディタの開発当初は MDI で作成していました。色々実装が大変だったのと子フォーム表示が遅いため、最終的にはタブ形式になりました。その当時に悩んだ子フォーム表示時のチラつきをなくす方法です。

最近減りましたね MDI のアプリ。あの代表的な Excel もやめちゃいましたもんね。でも Access はまだ MDI かも。

サンプルソース

子フォームを表示する際に MdiClient コントロールに対して描画を停止し子フォーム表示後に描画を再開することでチラツキをなくします。 描画再開後にリフレッシュしているのは再描画されるまで停止中の処理内容が反映されないためです。

MdiForm.cs

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Test {
    /// <summary>
    /// MDIの子フォームの表示時のチラツキをなくすサンプル
    /// </summary>
    public partial class MdiForm : Form {

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
            
        public const int WM_SETREDRAW = 0x000B;

        // MDIコントロール
        private MdiClient mdiClient;

        public MdiForm() {
            InitializeComponent();

            // MDIコントロール取得
            foreach (Control c in this.Controls) {
                if (c is MdiClient) {
                    this.mdiClient = (MdiClient)c;
                    break;
                }
            }
        }

        /// <summary>
        /// 子フォームを表示します。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ShowNewForm(object sender, EventArgs e) {
            // 子フォーム
            Form childForm = new Form();
            childForm.MdiParent = this;

            // 描画停止
            SendMessage(this.mdiClient.Handle, WM_SETREDRAW, new IntPtr(0), IntPtr.Zero);

            // 子フォーム表示
            childForm.Show();

            // 描画開始
            SendMessage(this.mdiClient.Handle, WM_SETREDRAW, new IntPtr(1), IntPtr.Zero);

            // 再描画
            this.Refresh();
        }
    }
}

解説

コンストラクタ

MdiClient(子フォームのコンテナ)を取得します。

ShowNewFormメソッド

新規に子フォームを表示するメソッドです。子フォームを表示する前に、MdiClient コントロール に対して描画を停止し表示後に描画を再開します。

おわりに

今回はMDIの子フォームを表示する際のチラつきをなくす方法ですが、例えばコントロールをフォームに追加するなどでチラつく場合も同様の方法で回避できます。

コメント

タイトルとURLをコピーしました