using System;
using System.Windows.Forms;

namespace MyScreenCap.Ctrl {

    /// <summary>
    /// ダイアログをOwnerWindowの中心に表示させる
    /// </summary>
    public static class ShowDialogAtCenter {

        /// <summary>
        /// 親ウィンドウ
        /// </summary>
        private static IWin32Window ownerWindow = null;

        /// <summary>
        /// フックハンドル
        /// </summary>
        private static IntPtr hHook = (IntPtr)0;

        /// <summary>
        /// Ownerウィンドウの中心にダイアログを表示
        /// </summary>
        /// <param name="dialog">ダイアログ</param>
        /// <param name="owner">owner window</param>
        /// <returns></returns>
        public static DialogResult ShowDialog(CommonDialog dialog, IWin32Window owner) {
            ownerWindow = owner;
            // フックを設定する。
            IntPtr hInstance = WinAPI.GetWindowLong(ownerWindow.Handle, WinAPI.GWL_HINSTANCE);
            IntPtr threadId = WinAPI.GetCurrentThreadId();
            hHook = WinAPI.SetWindowsHookEx(WinAPI.WH_CBT, new WinAPI.HOOKPROC(HookProc), hInstance, threadId);

            return dialog.ShowDialog();
        }

        /// <summary>
        /// フックプロシージャ
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        private static IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam) {

            if (nCode == WinAPI.HCBT_ACTIVATE) {
                WinAPI.RECT rcForm = new WinAPI.RECT(0, 0, 0, 0);
                WinAPI.RECT rcMsgBox = new WinAPI.RECT(0, 0, 0, 0);

                WinAPI.GetWindowRect(ownerWindow.Handle, out rcForm);
                WinAPI.GetWindowRect(wParam, out rcMsgBox);

                // センター位置を計算する。
                int x = (rcForm.Left + (rcForm.Right - rcForm.Left) / 2) - ((rcMsgBox.Right - rcMsgBox.Left) / 2);
                int y = (rcForm.Top + (rcForm.Bottom - rcForm.Top) / 2) - ((rcMsgBox.Bottom - rcMsgBox.Top) / 2);

                WinAPI.SetWindowPos(wParam, 0, x, y, 0, 0, WinAPI.SWP_NOSIZE | WinAPI.SWP_NOZORDER | WinAPI.SWP_NOACTIVATE);

                IntPtr result = WinAPI.CallNextHookEx(hHook, nCode, wParam, lParam);

                // フックを解除する。
                WinAPI.UnhookWindowsHookEx(hHook);
                hHook = (IntPtr)0;

                return result;

            } else {
                return WinAPI.CallNextHookEx(hHook, nCode, wParam, lParam);
            }
        }
    }
}
