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

Зачем использовать окно владельца в MessageBox.Show?

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

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

4b9b3361

Ответ 1

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

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

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


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

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

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

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

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

Чтобы все это хорошо работало с дочерними окнами, убедитесь, что у каждого дочернего окна есть свой набор свойств owner. Это произойдет автоматически, если вы вызываете ShowDialog() (что делает ваш пользовательский Form modal (и передаёт его параметр owner в те же случаи, когда вы проходили бы owner до 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().

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

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

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

Итак, если вы не вложили владение (window - (owns) → window - (owns) → messageBox), в противном случае владелецWindow устанавливает владельца, которого вы обычно выбираете.

Ответ 8

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

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


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