potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

C#&Win API MDI子フォームのStatusStripにサイズグリップを強制表示する。

以前の投稿でMDI子フォームはMDI親フォームの最大化時にサイズグリップが非表示になるWinFormsの仕様を紹介しました。この記事ではウィンドウメッセージとToolStripRendererを利用したサイズグリップの強制表示を紹介します。動作確認環境は.NET 8.0ですが、他のバージョンでも変わらないと思います。

使用する仕組みは次の3つです。

暗黙的なglobal usingを使った具体的なコードは以下の通りです。とりあえず機能することを目的としています。プロジェクトで使用するには次のコードを適用なCSファイルに貼り付け、目的とするフォームの「*.Designer.cs」でStatusStripStatusStripWithSizeGripに置き換えてください。

namespace Utility.Windows.Forms; // TODO:適当な名前空間に変更

internal sealed class StatusStripWithSizeGrip : StatusStrip
{
    protected override void OnCreateControl()
    {
        base.OnCreateControl();

        // SizeGripBoundsを使いたいのでサイズグリップを強制表示します。
        // この後の変更は対応しません。
        SizingGrip = true;
    }

    protected override void WndProc(ref Message m)
    {
        const int WM_NCHITTEST = 0x0084;
        const int HTBOTTOMRIGHT = 17;

        if (m.Msg == WM_NCHITTEST)
        {
            var pt = PointToClient(Cursor.Position);
            if (SizeGripBounds.Contains(pt))
            {
                m.Result = HTBOTTOMRIGHT;
                return;
            }
        }

        base.WndProc(ref m);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        // 直接の親がフォームかつ最小・最大化されていなければサイズグリップを描画
        if (Parent is not Form { WindowState: FormWindowState.Normal })
            return;

        // サイズグリップを描画する。描画済みでも上書き。
        Renderer.DrawStatusStripSizingGrip(new(e.Graphics, this));
    }
}