or said, 1 only way, and 2 kind of Invoking.
1. Make a new WindowForm who has centerParent Location, then copy it's location to the MessageBox by "Hook" the system dialog's location.
2. Just Hook the system dialog's location and set it before call MessageBox.Show()
Way 1:
CenterWinDialog
by Hans PassantThere's the code(class CenterWinDialog):
using System; using System.Text; using System.Drawing; using System.Windows.Forms; using System.Runtime.InteropServices; class CenterWinDialog : IDisposable { private int mTries = 0; private Form mOwner; public CenterWinDialog(Form owner) { mOwner = owner; owner.BeginInvoke(new MethodInvoker(findDialog)); } private void findDialog() { // Enumerate windows to find the message box if (mTries < 0) return; EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow); if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero)) { if (++mTries < 10) mOwner.BeginInvoke(new MethodInvoker(findDialog)); } } private bool checkWindow(IntPtr hWnd, IntPtr lp) { // Checks if <hwnd> is a dialog StringBuilder sb = new StringBuilder(260); GetClassName(hWnd, sb, sb.Capacity); if (sb.ToString() != "#32770") return true; // Got it Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size); RECT dlgRect; GetWindowRect(hWnd, out dlgRect); MoveWindow(hWnd, frmRect.Left + (frmRect.Width - dlgRect.Right + dlgRect.Left) / 2, frmRect.Top + (frmRect.Height - dlgRect.Bottom + dlgRect.Top) / 2, dlgRect.Right - dlgRect.Left, dlgRect.Bottom - dlgRect.Top, true); return false; } public void Dispose() { mTries = -1; } // P/Invoke declarations private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp); [DllImport("user32.dll")] private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp); [DllImport("kernel32.dll")] private static extern int GetCurrentThreadId(); [DllImport("user32.dll")] private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen); [DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc); [DllImport("user32.dll")] private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint); private struct RECT { public int Left; public int Top; public int Right; public int Bottom; } }
Usage:
private void button1_Click(object sender, EventArgs e) { using (new CenterWinDialog(this)) { MessageBox.Show("Nobugz waz here"); } }
Way 2: MessageBoxHelper by Jason Carr
There's the code(class MessageBoxHelper):
using System; using System.Runtime.InteropServices; using System.Windows.Forms; internal static class MessageBoxHelper { internal static void PrepToCenterMessageBoxOnForm(Form form) { MessageBoxCenterHelper helper = new MessageBoxCenterHelper(); helper.Prep(form); } private class MessageBoxCenterHelper { private int messageHook; private IntPtr parentFormHandle; public void Prep(Form form) { NativeMethods.CenterMessageCallBackDelegate callBackDelegate = new NativeMethods.CenterMessageCallBackDelegate(CenterMessageCallBack); GCHandle.Alloc(callBackDelegate); parentFormHandle = form.Handle; messageHook = NativeMethods.SetWindowsHookEx(5, callBackDelegate, new IntPtr(NativeMethods.GetWindowLong(parentFormHandle, -6)), NativeMethods.GetCurrentThreadId()).ToInt32(); } private int CenterMessageCallBack(int message, int wParam, int lParam) { NativeMethods.RECT formRect; NativeMethods.RECT messageBoxRect; int xPos; int yPos; if (message == 5) { NativeMethods.GetWindowRect(parentFormHandle, out formRect); NativeMethods.GetWindowRect(new IntPtr(wParam), out messageBoxRect); xPos = (int)((formRect.Left + (formRect.Right - formRect.Left) / 2) - ((messageBoxRect.Right - messageBoxRect.Left) / 2)); yPos = (int)((formRect.Top + (formRect.Bottom - formRect.Top) / 2) - ((messageBoxRect.Bottom - messageBoxRect.Top) / 2)); NativeMethods.SetWindowPos(wParam, 0, xPos, yPos, 0, 0, 0x1 | 0x4 | 0x10); NativeMethods.UnhookWindowsHookEx(messageHook); } return 0; } } private static class NativeMethods { internal struct RECT { public int Left; public int Top; public int Right; public int Bottom; } internal delegate int CenterMessageCallBackDelegate(int message, int wParam, int lParam); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool UnhookWindowsHookEx(int hhk); [DllImport("user32.dll", SetLastError = true)] internal static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("kernel32.dll")] internal static extern int GetCurrentThreadId(); [DllImport("user32.dll", SetLastError = true)] internal static extern IntPtr SetWindowsHookEx(int hook, CenterMessageCallBackDelegate callback, IntPtr hMod, int dwThreadId); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool SetWindowPos(int hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); } }
Usage:
private void button1_Click(object sender, EventArgs e) { MessageBoxHelper.PrepToCenterMessageBoxOnForm(this); MessageBox.Show("Hello!", "Hello!", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1, 0); }
0 件のコメント:
コメントを投稿