lex452, понятно. Указание родительской формы блокирует форму, но не ориентирует стандартный message box относительно неё.
Если хорошо подумать, то это логично. Бывают и достаточно маленькие формы, расположенные так, что центрированный относительно них message box не влезет в экран.
Поэтому остаётся два пути:
1) Создать собственный модальный dialog box (форму), настроить его, как хочется, и использовать вместо стандартного message box. Тут следует учитывать, что message box бывают оконными, задачными и общесистемными. Первые блокируют родительское окно, но сохраняют работоспособность других окон приложения, работающих в других потоках. Вторые блокируют всю задачу (все её потоки). Третьи блокируют все окна на экране у всех задач. Ещё следует учитывать, что стандартный message box обрабатывает комбинации клавиш "скопировать в буфер обмена" и копирует в буфер обмена выведенный текст, заголовок окна и кнопки (в текстовом виде). Т.е. полная собственная реализация message box не так проста.
2) Параллельно с вызовом message box запустит демона, который найдёт окно открытого message box и пошлёт ему системные сообщения, изменяющие его положение на экране. Этот вариант будет работать только для оконных message box, при котором другие потоки задачи не блокируются. И этот вариант обладает рядом рисков, связанных с нахождением нужного окна. Во-первых, если искать окно по заголовку, таких окон с одинаковым заголовком может оказаться несколько. Во-вторых, пользователь может нажать Enter или Esc достаточно быстро, чтобы message box закрылся сразу же после открытия, и демон, чтобы не зависнуть, должен этот случай предусматривать.
Первый вариант трудоёмкий, но не сложный.
Второй вариант интереснее. На скорую руку собранное решение выглядит примерно так:
        class MessageBox
        {
            struct Rect
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }
            [System.Runtime.InteropServices.DllImport("user32.dll")]
            static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
            [System.Runtime.InteropServices.DllImport("user32.dll")]
            static extern int GetWindowRect(IntPtr hWnd, ref Rect lpRect);
            [System.Runtime.InteropServices.DllImport("user32.dll")]
            static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
            private class DaemonParameters
            {
                public IntPtr ParentWindow;
                public string MessageBoxTitle;
            }
            private static void MoveMessageBox(IntPtr messageBox, DaemonParameters parameters)
            {
                Rect messageBoxArea = new Rect();
                int foundMessageBox = GetWindowRect(messageBox, ref messageBoxArea);
                if (foundMessageBox != 0)
                {
                    Rect parentWindowArea = new Rect();
                    int foundParentWindow = GetWindowRect(parameters.ParentWindow, ref parentWindowArea);
                    if (foundParentWindow != 0)
                    {
                        int widthDifference = (parentWindowArea.Right - parentWindowArea.Left) - (messageBoxArea.Right - messageBoxArea.Left);
                        int heightDifference = (parentWindowArea.Bottom - parentWindowArea.Top) - (messageBoxArea.Bottom - messageBoxArea.Top);
                        int x = parentWindowArea.Left + widthDifference / 2;
                        int y = parentWindowArea.Top + heightDifference / 2;
                        SetWindowPos(messageBox, IntPtr.Zero, x, y, 0, 0, 0x0001);
                    }
                }
            }
            private static IntPtr FindMessageBox(DaemonParameters parameters)
            {
                return FindWindow(null, parameters.MessageBoxTitle);
            }
            private static void RunDaemon(object param)
            {
                try
                {
                    DaemonParameters parameters = param as DaemonParameters;
                    bool isDone = false;
                    while(!isDone)
                    {
                        System.Threading.Thread.Sleep(1);
                        IntPtr handle = FindMessageBox(parameters);
                        if (handle != IntPtr.Zero)
                        {
                            MoveMessageBox(handle, parameters);
                            isDone = true;
                        }
                    }
                }
                catch(System.Threading.ThreadAbortException)
                {
                }
            }
            private static System.Threading.Thread BeginDaemon(DaemonParameters parameters)
            {
                System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(RunDaemon));
                thread.Start(parameters);
                return thread;
            }
            private static void EndDaemon(System.Threading.Thread thread)
            {
                if (thread.IsAlive)
                {
                    thread.Abort();
                }
            }
            public static System.Windows.Forms.DialogResult Show(System.Windows.Forms.Form parentWindow, string text, string caption)
            {
                DaemonParameters parameters = new DaemonParameters();
                parameters.ParentWindow = parentWindow.Handle;
                parameters.MessageBoxTitle = caption;
                System.Threading.Thread daemonThread = BeginDaemon(parameters);
                System.Windows.Forms.DialogResult result = System.Windows.Forms.MessageBox.Show(parentWindow, text, caption);
                EndDaemon(daemonThread);
                return result;
            }
        }
При этом стандартный класс MessageBox перекрывается собственным. Всякие параметры, связанные с украшательствами, можно добавить самостоятельно. Обязательно нужно указывать заголовок message box, при этом у разных message box должны быть разные заголовки, иначе не будет работать. Но если заменить алгоритм поиска окна, используя вместо FindWindow что-нибудь другое - например через GetWindow или т.п. функции перебирать все окна и потом разными запросами идентифицировать нужное, то и это ограничение можно обойти.