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

Загрузка и отображение событий в Windows Forms

Надеюсь, я просто пропустил что-то очевидное, но я пытаюсь разобраться в различиях между событиями Load и Show в Windows Forms.

Традиционно я использовал Load (или фактически OnLoad, так как я считаю, что более чистое переопределение метода, чем полагаться на конструктор, чтобы подключить событие к себе), поскольку он доступен во всех версиях .NET., С .NET 2.0 было представлено событие Shown.

Теперь, если вы посмотрите описания для них в документации MSDN ( "Загрузить: Происходит до того, как форма отображается в первый раз"., "Показывается: Происходит всякий раз, когда форма впервые отображается".) это звучит как должно происходить событие Load, тогда форма должна стать видимой, тогда должно произойти событие Shown; комбинация двух, что позволяет выполнять некоторые задачи как до, так и после формы. Имеет смысл, правильно?

Однако эксперимент показал, что событие Shown неизменно встречается перед событием Load, всякий раз, когда я его пытаюсь (и оба возникают до того, как форма становится видимой). И все же, когда я google вокруг всякий раз, когда я обнаруживаю страницу, в которой говорится о порядке, в котором эти события запущены, они всегда перечисляют начальное событие Load.

Я просто схожу с ума, или я что-то пропустил? (И если они происходят примерно в одно и то же время, то почему было добавлено событие Shown?)

(Мое текущее решение для того, чтобы что-то делать до и после показа формы, - использовать OnLoad для "до показа" и запускать таймер с одним выстрелом для "после показа", который работает нормально и надежно, но это немного уродливо, и я надеялся, что есть более чистое решение. Но похоже, что событие Shown не так.)

4b9b3361

Ответ 1

Избегайте использования MessageBox.Show() для его отладки. Он накачивает контур сообщения, нарушая нормальный поток событий. Событие Load запускается Windows, отправляя сообщение WM_SHOWWINDOW, перед тем, как окно станет видимым. Нет уведомления Windows о том, что "ваше окно теперь полностью показано", поэтому дизайнеры WF придумали трюк для создания события Shown. Они используют Control.BeginInvoke(), гарантируя, что метод OnShown() вызывается, как только программа снова простаивает и повторно входит в цикл сообщения.

Этот трюк имеет множество других применений, особенно когда вам приходится задерживать выполнение кода, запускаемого событием. Однако в вашем случае он разваливается, потому что вы используете MessageBox.Show(). Его цикл сообщений отправляет делегат, зарегистрированный в BeginInvoke(), заставляя событие Shown запускаться до того, как будет показано окно.

Существует множество других способов получить диагностику помимо MessageBox. Debug.Print() и Console.WriteLine() удобны, их вывод идет в Окно вывода Visual Studio без каких-либо негативных последствий для нормального последовательность срабатывания событий. Простая точка может творить чудеса.

Ответ 2

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

Прослеживаемые события

Форма - Изменен размер клиента: 8/14/2010 10:40:28 AM
Form - Control Added - button1: 8/14/2010 10:40:29 AM
Форма - конструктор: 8/14/2010 10:40:29 AM
Form - Handle Создано: 8/14/2010 10:40:29 AM
Форма - недействительна: 8/14/2010 10:40:29 AM
Форма - Форма Загрузка: 8/14/2010 10:40:29 AM
Форма - загружена: 14.08.2010 10:40:29
Форма - Создать контроль: 8/14/2010 10:40:29 AM
Форма - OnActivated: 8/14/2010 10:40:29 AM
Форма - показано: 14.08.2010 10:40:29
Форма - OnPaint: 8/14/2010 10:40:29 AM
Форма - недействительна: 8/14/2010 10:40:29 AM
Форма - OnPaint: 8/14/2010 10:40:29 AM

Ответ 3

Событие Shown происходит после события Load. Основное различие заключается не в видимости формы, а в ее состоянии (ширина, высота и т.д.).

Чтобы пояснить, вот пример. Рассмотрим форму, которая имеет размер по умолчанию 100, 200 и WindowState, который равен Maximized. В обработчике событий Load размер будет 100, 200. Но в обработчике событий Shown размер будет размером вашего экрана.

Ответ 4

Хорошо, я думаю, что я разработал то, что действительно происходит сейчас, и откуда возникла моя путаница (хотя и не потому, что так ведет себя). Похоже, что событие Shown на самом деле происходит внутри события Load.

С учетом этого кода:

 protected override OnLoad(EventArgs e)
{
    MessageBox.Show("Enter Load");
    base.OnLoad(e);
    MessageBox.Show("Exit Load");
}

protected override OnShown(EventArgs e)
{
    MessageBox.Show("Enter Shown");
    base.OnShown(e);
    MessageBox.Show("Exit Shown");
}

тогда сообщения отображаются в следующем порядке:

  • Введите Load
  • Введите отображаемый
  • Exit Show
  • Exit Load

Свойство Visible является True во всех четырех случаях, но ни в одном из этих случаев форма, видимая на экране (покрашена).

Действительно странно, что если я прокомментирую сообщение "Выход из загрузки", то форма появится на экране до появится сообщение "Enter Shown". Кажется, что код был выполнен после вызова базовой OnLoad, что он действительно возражает против.

Ответ 5

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

выполните быстрый тест с пустым проектом:

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    MsgBox("load") 'form is still visible = false
End Sub

Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
    MsgBox("shown") ' form is now visible = true
End Sub
End Class

Ответ 6

Я только что проверил и загрузил огни перед тем, как это показано.

В вашем подходе явно что-то не так.