using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Interop; using System.Runtime.InteropServices; namespace GetADoc { //親(メイン)ウインドウの中心にメッセージを表示するためのクラス class CustomMsgBox {/// /// 親ウィンドウ /// private Window ownerWindow = null; /// /// フックハンドル /// private IntPtr hHook = IntPtr.Zero; /// /// メッセージボックスを表示する /// /// /// /// /// /// /// public static MessageBoxResult Show( Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon) { if (owner.WindowState == WindowState.Minimized) { return MessageBox.Show(owner, messageBoxText, caption, button, icon); } else { CustomMsgBox mbox = new CustomMsgBox(owner); return mbox.Show(messageBoxText, caption, button, icon); } } /// /// コンストラクタ /// /// Owner Window private CustomMsgBox(Window window) { ownerWindow = window; } /// /// メッセージボックスを表示する /// /// /// /// /// /// private MessageBoxResult Show( string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon) { // フックを設定する。 HwndSource hwndSource = (HwndSource)HwndSource.FromVisual(ownerWindow); IntPtr hInstance = WinAPI.GetWindowLong(hwndSource.Handle, WinAPI.GWL_HINSTANCE); IntPtr threadId = WinAPI.GetCurrentThreadId(); hHook = WinAPI.SetWindowsHookEx(WinAPI.WH_CBT, new WinAPI.HOOKPROC(HookProc), hInstance, threadId); return MessageBox.Show(ownerWindow, messageBoxText, caption, button, icon); } /// /// フックプロシージャ /// /// /// /// /// private 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); HwndSource hwndSource = (HwndSource)HwndSource.FromVisual(ownerWindow); WinAPI.GetWindowRect(hwndSource.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.Zero; return result; } else { return WinAPI.CallNextHookEx(hHook, nCode, wParam, lParam); } } } internal class WinAPI { [DllImport("user32.dll")] public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("kernel32.dll")] public static extern IntPtr GetCurrentThreadId(); [DllImport("user32.dll")] public static extern IntPtr SetWindowsHookEx(int idHook, HOOKPROC lpfn, IntPtr hInstance, IntPtr threadId); [DllImport("user32.dll")] public static extern bool UnhookWindowsHookEx(IntPtr hHook); [DllImport("user32.dll")] public static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); public delegate IntPtr HOOKPROC(int nCode, IntPtr wParam, IntPtr lParam); public const int GWL_HINSTANCE = (-6); public const int WH_CBT = 5; public const int HCBT_ACTIVATE = 5; public const int SWP_NOSIZE = 0x0001; public const int SWP_NOZORDER = 0x0004; public const int SWP_NOACTIVATE = 0x0010; public struct RECT { public RECT(int inLeft, int inTop, int inRight, int inBottom) { Left = inLeft; Top = inTop; Right = inRight; Bottom = inBottom; } public int Left; public int Top; public int Right; public int Bottom; } } }