Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
OrganizationEventAdvent CalendarQiitadon (β)
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at




MessageBox.Show だと画面中央にメッセージボックスが表示され、オーナーフォーム (親ウィンドウ) の中央に表示するためのパラメーターは存在しない。


オーナーフォームの中央に表示するには、Win32 API を使う必要がある。

static class CustomMessageBox
    static class Win32Native
        #region GetWindowLong
        static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
        const int GWL_HINSTANCE = -6;

        public static IntPtr GetWindowHInstance(IntPtr hWnd) => GetWindowLong(hWnd, GWL_HINSTANCE);

        public static extern IntPtr GetCurrentThreadId();

        #region WindowsHookEx
        static extern IntPtr SetWindowsHookEx(int idHook, HOOKPROC lpfn, IntPtr hInstance, IntPtr threadId);
        const int WH_CBT = 5;
        public static IntPtr SetWindowsHookEx(HOOKPROC lpfn, IntPtr hInstance, IntPtr threadId) => SetWindowsHookEx(WH_CBT, lpfn, hInstance, threadId);

        public static extern bool UnhookWindowsHookEx(IntPtr hHook);
        public static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, IntPtr lParam);

        public delegate IntPtr HOOKPROC(int nCode, IntPtr wParam, IntPtr lParam);
        public const int HCBT_ACTIVATE = 5;

        #region GetWindowRect
        static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
        public struct RECT
            public int Left, Top, Right, Bottom;
            public int Width => this.Right - this.Left;
            public int Height => this.Bottom - this.Top;

        public static RECT GetWindowRect(IntPtr hWnd)
            RECT rc;
            GetWindowRect(hWnd, out rc);
            return rc;

        #region SetWindowPos
        static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
        const uint SWP_NOSIZE = 0x0001;
        const uint SWP_NOZORDER = 0x0004;
        const uint SWP_NOACTIVATE = 0x0010;

        public static bool SetWindowPos(IntPtr hWnd, int x, int y)
            var flags = SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE;
            return SetWindowPos(hWnd, 0, x, y, 0, 0, flags);

    public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
        hOwner = owner.Handle;
        var hInstance = Win32Native.GetWindowHInstance(owner.Handle);
        var threadId = Win32Native.GetCurrentThreadId();
        hHook = Win32Native.SetWindowsHookEx(new Win32Native.HOOKPROC(HookProc), hInstance, threadId);
        return MessageBox.Show(owner, text, caption, buttons, icon);

    private static IntPtr hOwner = (IntPtr)0;
    private static IntPtr hHook = (IntPtr)0;
    private static IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam)
        if (nCode == Win32Native.HCBT_ACTIVATE)
            // オーナーウィンドウとメッセージボックスの領域を取得
            var rcOwner = Win32Native.GetWindowRect(hOwner);
            var rcMsgBox = Win32Native.GetWindowRect(wParam);

            // メッセージボックスをオーナーウィンドウの中央位置に移動
            var x = rcOwner.Left + (rcOwner.Width - rcMsgBox.Width) / 2;
            var y = rcOwner.Top + (rcOwner.Height - rcMsgBox.Height) / 2;
            Win32Native.SetWindowPos(wParam, x, y);

            // フックを解除
            hHook = (IntPtr)0;
        return Win32Native.CallNextHookEx(hHook, nCode, wParam, lParam);


通常の MessageBox と同じく、CustomMessageBox クラスの Show メソッドを呼ぶ。

CustomMessageBox.Show(owner, "メッセージ", "タイトル", MessageBoxButtons.OK, MessageBoxIcon.Information);
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Help us understand the problem. What are the problem?