C#.NET で MessageBox をオーナーウィンドウの中央に表示するための覚え書きです。
元ネタは Microsoft のサポート技術情報 180936 です。
※ソースだけですが。。。
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void cmdCenterMsgBox_Click(object sender, EventArgs e) {
MsgBox.Show(this, "オーナーウィンドウの中央に表示されるはず", "オーナーウィンドウの中央表示サンプル", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
/// <summary>
/// Win API
/// </summary>
public 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 left, int top, int right, int bottom) {
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
public int Left;
public int Top;
public int Right;
public int Bottom;
}
}
/// <summary>
/// オーナーウィンドウの真中に表示される MessageBox
/// </summary>
public class MsgBox {
/// <summary>
/// 親ウィンドウ
/// </summary>
private IWin32Window m_ownerWindow = null;
/// <summary>
/// フックハンドル
/// </summary>
private IntPtr m_hHook = (IntPtr) 0;
/// <summary>
/// メッセージボックスを表示する
/// </summary>
/// <param name="owner"></param>
/// <param name="messageBoxText"></param>
/// <param name="caption"></param>
/// <param name="button"></param>
/// <param name="icon"></param>
/// <returns></returns>
public static DialogResult Show(
IWin32Window owner,
string messageBoxText,
string caption,
MessageBoxButtons button,
MessageBoxIcon icon) {
MsgBox mbox = new MsgBox(owner);
return mbox.Show(messageBoxText, caption, button, icon);
}
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="window">親ウィンドウ</param>
private MsgBox(IWin32Window window) {
m_ownerWindow = window;
}
/// <summary>
/// メッセージボックスを表示する
/// </summary>
/// <param name="messageBoxText"></param>
/// <param name="caption"></param>
/// <param name="button"></param>
/// <param name="icon"></param>
/// <returns></returns>
private DialogResult Show(
string messageBoxText,
string caption,
MessageBoxButtons button,
MessageBoxIcon icon) {
// フックを設定する。
IntPtr hInstance = WinAPI.GetWindowLong(m_ownerWindow.Handle, WinAPI.GWL_HINSTANCE);
IntPtr threadId = WinAPI.GetCurrentThreadId();
m_hHook = WinAPI.SetWindowsHookEx(WinAPI.WH_CBT, new WinAPI.HOOKPROC(HookProc), hInstance, threadId);
return MessageBox.Show(m_ownerWindow, messageBoxText, caption, button, icon);
}
/// <summary>
/// フックプロシージャ
/// </summary>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
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);
WinAPI.GetWindowRect(m_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(m_hHook, nCode, wParam, lParam);
// フックを解除する。
WinAPI.UnhookWindowsHookEx(m_hHook);
m_hHook = (IntPtr) 0;
return result;
} else {
return WinAPI.CallNextHookEx(m_hHook, nCode, wParam, lParam);
}
}
}
Visual Studio 2005 で作成しました。
ソース一式 (MessageBoxSample.zip) (11.1 KB)