Подтвердить что ты не робот

Почему не MessageBox TopMost?

Недавно я узнал, что по умолчанию MessageBoxes не были самой верхней формой при отображении по умолчанию, и мне было интересно, если кто-нибудь знает какие-либо обстоятельства, когда вы не хотите, чтобы окно сообщений отображалось поверх других окон?

Я обнаружил проблему, когда начал показывать экраны всплесков во время загрузки приложения, и похоже, что моя программа все еще работала, но за заставкой, ожидавшей ввода, был MessageBox. Заставка была показанный в другом потоке в поток, который называется ящиком сообщений, поэтому я представляю себе, почему он не появился над всплеском; но это все еще не объясняет, почему MessageBox по умолчанию не имеет флага MB_TOPMOST?

Edit

Чтобы лучше уточнить: в конце концов, я должен был сделать что-то похожее на это, чтобы в конце создать почтовый ящик, код не совсем корректен, как написано из памяти)

[DllImport("User32.dll")]
private int extern MessageBox(windowhandle, message, caption, flag);
public static void MessageBox(windowhandle, string message, string caption)
{
    MessageBox(windowhandle, message,caption, MB_TOPMOST);
}
4b9b3361

Ответ 1

Чтобы показать MessageBox в первую очередь для приложения

код

//Should be MessageBox.Show() below
MessageBox.Show(this, "My top most message");

Причина не быть MB_TOPMOST по умолчанию

Если MB_TOPMOST будет по умолчанию, то MessageBox будет отображаться в режиме "система мода", и он будет точно на вершине этой формы, и побочные эффекты состоят в том, что режим "модальный мода" вызовет MessageBox для блокировки окон до тех пор, пока сообщение не будет уволено, обычно это будет режим "мода приложения".

Ссылки ссылки

Ответ 2

Предлагаемые решения работают, если вы можете получить дескриптор или ссылку на окно, диалог должен появиться поверх. Однако это не всегда возможно или легко достичь:

  • окно является заставкой и не должно тесно связываться с вашей бизнес-логикой.
  • окно создается другим классом или библиотекой, чем текущий
  • окно выходит из-под контроля, то есть из сторонней (родной) библиотеки

В таких сценариях вы можете использовать API-интерфейс Win232 MessageBox от User32.dll, но также доступно более простое управляемое решение:

MessageBox.Show(new Form { TopMost = true }, "Hello, I'm on top!");

Код new Form { TopMost = true } создаст скрытую форму с свойством MB_TOPMOST, которая наследуется диалоговым окном в окне сообщений. В результате он появится поверх всех ваших других окон. Использование new Form() inline не имеет побочных эффектов, не имеет видимого внешнего вида и обычно будет уничтожаться через сборщик мусора.

Примечание. Если вы уже не в форме, не забудьте пространство имен, это System.Windows.Forms.MessageBox, а не System.Windows.MessageBox! (спасибо, user1).

Ответ 3

При показе MessageBox предоставить его владельцу в качестве первого аргумента. Например, при вызове вызова Form:

MessageBox.Show(this, "Message");

Укажите ссылку на окно, в котором он будет использоваться в качестве первого аргумента.

Ящики сообщений (и модальные формы в целом) не отображаются поверх всех окон вашего приложения. Они появляются только поверх их владельца. Если вы хотите, чтобы ваше окно сообщений (или другие модальные формы) находилось поверх вашего заставки, установите их владельца в экземпляр формы всплеска.

Ответ 4

Я пытаюсь вставить более полный фрагмент кода, он определенно работает

    [CLSCompliant(false)]
    [DllImport("user32.dll", EntryPoint = "MessageBox")]
    public static extern int MessageBoxUser32(int hWnd, String text, String caption, uint type);

    const uint MB_TOPMOST = 0x00040000;
    const uint MB_OK  = 0x00000000;
    const uint MB_OKCANCEL = 0x00000001;
    const uint MB_ABORTRETRYIGNORE = 0x00000002;
    const uint MB_YESNOCANCEL = 0x00000003;
    const uint MB_YESNO = 0x00000004;
    const uint MB_RETRYCANCEL = 0x00000005;

     public static void ShowMessageBox(string message, bool topMost = true
        , string title = null, MessageBoxButtons buttons = MessageBoxButtons.OK)
    {
        if(topMost)
        {
            uint mbv = MB_TOPMOST;

            if (buttons == MessageBoxButtons.OK)
                mbv |= MB_OK;
            if (buttons == MessageBoxButtons.OKCancel)
                mbv |= MB_OKCANCEL;
            if (buttons == MessageBoxButtons.AbortRetryIgnore)
                mbv |= MB_ABORTRETRYIGNORE;
            if (buttons == MessageBoxButtons.YesNoCancel)
                mbv |= MB_YESNOCANCEL;
            if (buttons == MessageBoxButtons.YesNo)
                mbv |= MB_YESNO;
            if (buttons == MessageBoxButtons.RetryCancel)
                mbv |= MB_RETRYCANCEL;

            MessageBoxUser32(0, message, title == null ? string.Empty : title, MB_TOPMOST);
        }
        else
        {
            MessageBox.Show(message, title == null ? string.Empty : title, buttons);
        }
    }

Ответ 5

Ответ, приведенный выше, явно правильный, минус тот факт, что ему нужно вызвать System.iDisposable. Установить на объект новую форму.

MessageBoxButtons buttons = MessageBoxButtons.YesNo;
MessageBoxIcon icon = MessageBoxIcon.Error;
string message = Resources.ResourceManager.GetString("MESSAGE");
string caption = Resources.ResourceManager.GetString("TITLE");
DialogResult result;
Form form;
using (form = new Form())
{
    form.TopMost = true;
    result = MessageBox.Show(form, caption, message, buttons, icon);
}
if (result == DialogResult.Yes)
{
    // do something with the result
}

Подробнее:

Примеры Top-Most-MessageBox