2013-04-19 3 views
33

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

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

Редактировать

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

[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); 
} 

ответ

22

Чтобы показать MessageBox на самой верхней из всех для применения

Код

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

Причина для не будучи MB_TOPMOST по умолчанию

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

Справочные ссылки

  1. MSDN forum - How to display a MessageBox as topmost window
  2. SO - C# MessageBox To Front When App is Minimized To Tray
+1

Этот ответ выглядит великолепно! но я думал, что в любом случае блокировки окон заблокированы? – Sayse

+0

Из форума [msdn, упомянутого в ответе] (http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/7a515f66-8818-4ec5-9213-7ee479f8fb18/) Я обнаружил, что есть что-то вроде 'system modal' и' application modal'. Может быть, я еще раз позабочусь об этом подробнее. –

+0

Только модальные окна сообщений образуют свои формы, а «обычный» все равно сохраняется даже после выхода из программы, которая породила его. – Tory

2

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

MessageBox.Show(this, "Message"); 

Предоставить ссылку на окно, владеющее его в качестве первого аргумента.

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

+0

Я не понимаю ваш ответ .. как бы это обеспечить, чтобы почтовый ящик всегда был над всеми другими окнами? или что это достигается? – Sayse

+0

Это не так. Он всегда будет поверх своего владельца. Если вы хотите, чтобы он появился поверх экрана всплеска, установите его владельца в экземпляр заставки. –

52

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

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

В таких случаях, вы могли использовать Win232 MessageBox API от User32.dll, а си mpler, управляемое решение также доступно:

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

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

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

+1

Интересный подход, выбранный ответ сделан из-за разницы между модальным модальным и системным модальным. Предположим, что ваш подход будет по-прежнему поддерживать приложение Messagebox в моделе и будет полезен в обстоятельствах, которые вы указали.+1 – Sayse

+0

@Sayse: действительно, он поддерживает приложение Messagebox modal. Мы много используем его в библиотечных методах бизнес-логики, которым разрешено открывать окно сообщений, но просто громоздко всегда нужно передавать текущую форму в качестве параметра. – Abel

+4

Просто для разъяснения для других это 'System.Windows.Forms.MessageBox' не' System.Windows.MessageBox' – user1

0

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

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 Examples

1

Я стараюсь, чтобы вставить более полный кусок кода, это определенно работает

[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); 
     } 
    } 
Смежные вопросы