Зачем использовать окно владельца в MessageBox.Show? - PullRequest
19 голосов
/ 12 октября 2008

MessageBox.Show имеет такие формы, как MessageBox.Show (ownerWindow, ....).

Что я получу, назначив окно владельца?

Ответы [ 8 ]

22 голосов
/ 12 октября 2008

Окно сообщения - это модальная форма, что означает, что его родительское окно отключено до тех пор, пока окно сообщения не будет закрыто.

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

Другие темы могут создавать окна сообщений без родительской формы. Это может быть плохой ситуацией, поскольку оно может находиться за активным окном, и пользователь даже не узнает, что оно там, пока не закроет программу. Чтобы избежать этого, вы можете передать дескриптор главного окна приложения методу Show, который отключит это окно на время сообщения.


ДОБАВЛЕНО: Я думал об этом, и теперь я не уверен. Отрывок из отражателя, который вы дали ниже, заставляет меня думать, что, возможно, нить не имеет значения. (Я сказал, что ничего не могу найти в документации!)

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

Извините за путаницу.

Теперь я рекомендую никогда не указывать этот параметр, если вам не нужно что-то кроме активного окна в качестве главной формы.

3 голосов
/ 12 октября 2008

Установка владельца приводит к отключению владельца при открытом окне сообщения.

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

2 голосов
/ 11 августа 2014

На основании тестирования и этого другого ответа , .net автоматически выберет текущее окно, находящееся в фокусе, в той же цепочке, что и ваш вызов MessageBox.Show(). Чтобы получить правильное поведение, вы должны убедиться, что вы отображаете MessageBox из того же потока, что и это окно и укажите окно, с которым MessageBox логически связано как его owner. A MessageBox только модально блокирует ввод других Form s в потоке, из которого он запущен. Вероятно, это связано с тем, как MessageBox делает себя модальным (может быть, он перехватывает сообщения, направленные на текущий поток, и пропускает только некоторые сообщения в другие окна, кроме себя?). Эффект модальной блокировки ввода состоит в том, что пользователь не сможет сфокусировать эти окна или какие-либо элементы управления внутри них, и попытка сделать это производит звук «Дин». Также, если владелец не указан, MessageBox автоматически выберет активное окно в текущем потоке. Если текущее активное окно принадлежит другому потоку (или другому приложению!), У MessageBox не будет владельца. Это означает, что он получает свою собственную запись панели задач: он ведет себя как свое собственное отдельное окно. Пользователь может открывать другие окна в вашем приложении (даже если пользователь не может взаимодействовать с ними). Вы можете получить ситуацию, когда ваша программа перестает отвечать на ввод пользователя, когда пользователь запутался, потому что пользователь каким-то образом поднял главное окно вашего приложения после отображения диалогового окна. Однако, если владелец настроен правильно, попытка поднять главное окно вызовет подъем и мигание MessageBox.

Чтобы все это хорошо работало с дочерними окнами, убедитесь, что для каждого дочернего окна установлено свойство Owner. Это произойдет автоматически, если вы вызовете ShowDialog() (что делает ваш пользовательский Form модальным (и do передает его параметр owner в тех же случаях, когда вы передаете * 1031). * до MessageBox.Show())).

Теперь большинство кодировок winforms состоит в написании кода непосредственно в обработчики событий внутри подкласса Form. При написании обработчиков событий winforms вы можете предположить много вещей. Во-первых, вы никогда не должны вызывать this.Invoke() в качестве оператора верхнего уровня в обработчике событий GUI, потому что такие обработчики всегда выполняются в том же потоке, в котором был создан подкласс Form. Во-вторых, для многих (но не всех) этих обработчиков можно предположить, что Form имеет фокус (и, таким образом, MessageBox.Show() будет автоматически выбран его владельцем). Например, при написании кода внутри обработчика события Click кнопки (возможно, с именем button1_Click) вы можете смело предполагать, что форма сфокусирована (потому что вызов PerformClick() для Button другой формы - плохая практика). Однако Timer.Tick может произойти, даже если ваша форма не сфокусирована. Так, в случае Timer.Tick, нет необходимости Invoke() (как и в любом другом обработчике событий winforms) , но - это необходимость указывать owner. Последний случай сложнее заметить, поскольку разработчик должен сфокусировать свое приложение, чтобы заметить, что диалоговое окно, отображаемое в этом случае, ведет себя немного иначе, чем когда фокусируется его приложение. Так, укажите owner всякий раз, когда вам нужно использовать Invoke() или , если возможно, чтобы событие было запущено, когда окно не сфокусировано. Это руководство применяется при вызове MessageBox.Show() и Form.ShowDialog().

Большая часть того, что я здесь обсуждаю, является результатом возни с при чтении других ответов.

1 голос
/ 27 августа 2016

Звонок MessageBox.Show(frmMain,"a message","a title") добавляет форму TextDialog в коллекцию форм Application.OpenForms() приложения, а также саму главную форму frmMain. Он остается после закрытия окна сообщений.

Я только что обнаружил 14 из них, когда позвонил btnOK_Click() и установил точку останова.

Когда я позвонил frmMain.Close(), чтобы закрыть основную форму, ничего не произошло. frmMain не закроется, пока не закроются все 14 Application.OpenForms или вы должны вызвать Application.Exit().

1 голос
/ 13 октября 2008

Оказывается, владение окном не является переходным. В случае, если у вас есть форма, порождающая форму, порождающая MessageBox, в MessageBox.Show должен использоваться параметр ownerWindow. Исходная форма должна быть установлена ​​в качестве окна владельца MessageBox.

0 голосов
/ 27 мая 2010

Документация, по-видимому, подразумевает, что единственная цель параметра владельца - если вы укажете MB_HELP, окно сообщения знает, в какое окно оно должно отправить сообщение WM_HELP.

http://msdn.microsoft.com/en-us/library/ms645505%28VS.85%29.aspx


О, только что понял, что ОП был о .net - я дал ответ про winapi - извините!

0 голосов
/ 12 октября 2008

Используя Net Reflector, я только что нашел этот код в Messagebox.Show:

else if (owner == IntPtr.Zero)
    owner = UnsafeNativeMethods.GetActiveWindow();

Так что, если вы не вложите владение (window - (владение) -> window - (владение) -> messageBox), оставив поле ownerWindow, вы установите владельца, которого вы обычно выбираете.

0 голосов
/ 12 октября 2008

, если я не ошибаюсь, это мешает владельцу открыть окно Focus (), пока окно сообщений не закроется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...