На основании тестирования и этого другого ответа , .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()
.
Большая часть того, что я здесь обсуждаю, является результатом возни с при чтении других ответов.