Почему не 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);
}
Ответы
Ответ 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