Обработка события контролом на форме после её уничтожения

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Обработка события контролом на форме после её уничтожения

Сообщение asharky » 16.06.2007 (Сб) 20:34

Хотел бы получить совет, как наиболее правильно поступить в следующей ситуации:

Приложение Windows Form. Стартовая форма: fMain. На ней в числе контролов имеется кнопка уничтожения формы: btnQuit. Кнопка оснащена парой разных картинок, которые отрабатываются событиями MouseHover и MouseLeave. По событию btnQuit.Click форма уничтожается:

Код: Выделить всё
   Private Sub btnQuit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnQuit.Click
      Me.Dispose()
   End Sub


Но! Во время работы Me.Dispose() успевает сработать событие btnQuit.MouseLeave и вызвать исключение в связи с отсутствием на форме контрола imglstCommandKey:
Код: Выделить всё
   Private Sub btnQuit_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnQuit.MouseLeave
      Me.btnQuit.Image = Me.imglstCommandKey.Images(0)
   End Sub


Выход из ситуации прост:
Код: Выделить всё
   Private Sub btnQuit_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnQuit.MouseLeave
      Try
         Me.btnQuit.Image = Me.imglstCommandKey.Images(0)
      Catch ex As Exception
      End Try
   End Sub

или
Код: Выделить всё
   Private Sub btnQuit_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnQuit.MouseLeave
      If Not Me.Disposing Then
         Me.btnQuit.Image = Me.imglstCommandKey.Images(0)
      End If
   End Sub

но как-то мне это не нравится совершенно :(

Как можно иначе оформить код, чтобы было "в духе .NET" :?:

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 16.06.2007 (Сб) 21:07

в btnQuit_Click
Код: Выделить всё
Me.Close
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Сообщение asharky » 16.06.2007 (Сб) 23:19

Nord777 писал(а):в btnQuit_Click
Код: Выделить всё
Me.Close
Ничего не меняется. У меня по крайней мере.

Может кто попробует?

Код: Выделить всё
Public Class fMain


   Private Sub btnQuit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
   Handles btnQuit.Click
      Me.Close()
   End Sub

   Private Sub btnQuit_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) _
   Handles btnQuit.MouseLeave
      Me.btnQuit.Image = Me.imglstCommandKey.Images(0)
   End Sub

   Private Sub btnQuit_MouseHover(ByVal sender As Object, ByVal e As System.EventArgs) _
   Handles btnQuit.MouseHover
      Me.btnQuit.Image = Me.imglstCommandKey.Images(1)
   End Sub

End Class


По нажанию на кнопку выхода вываливается Exception в процедуре btnQuit_MouseLeave.

ЗЫ. На форме fMain имеется контрол imglstCommandKey типа imageList, в котором прописана пара картинок.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 17.06.2007 (Вс) 12:23

Код: Выделить всё
If imglstCommandKey.Images.Count = 0 Then Exit Sub
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Сообщение asharky » 17.06.2007 (Вс) 13:33

Nord777 писал(а):
Код: Выделить всё
If imglstCommandKey.Images.Count = 0 Then Exit Sub
Понятно. Значит получается, что без обработки "особенной ситуации" всё-таки не обойтись. Печально :(

Спасибо!

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 17.06.2007 (Вс) 14:23

И что же в этом печального?
Какие то проблемы?
Можешь так написать:
Код: Выделить всё
    Private Sub btnQuit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnQuit.Click
        RemoveHandler btnQuit.MouseLeave, AddressOf btnQuit_MouseLeave
        Me.Close()
    End Sub
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Сообщение asharky » 17.06.2007 (Вс) 22:00

Nord777 писал(а):И что же в этом печального?
Какие то проблемы?
Да, проблемы. Морально-этического плана :)

Получается не красивый код какой-то. И дело не в подчерке, а в специальной обработке события, которого, по логике, быть не должно. Форма и объекты уничтожены, и вдруг вылезает событие. Откуда оно? Зачем? Что за "привет с того света"? Меня лично это как-то напрягает :)

Nord777 писал(а):Можешь так написать:
Код: Выделить всё
    Private Sub btnQuit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnQuit.Click
        RemoveHandler btnQuit.MouseLeave, AddressOf btnQuit_MouseLeave
        Me.Close()
    End Sub
Ну это ещё один вариант обработки, не более того. Спасибо.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 17.06.2007 (Вс) 22:28

Форма и объекты уничтожены, и вдруг вылезает событие

Обработчик события есть код. Код может работать и без формы.
В твоём случае ImageList принадлежит форме поэтому такая бодяга и происходит. Держи свои картинки в массиве или ресурсах, тогда не придется писать аж целую строку кода.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Сообщение asharky » 17.06.2007 (Вс) 23:12

Nord777 писал(а):Обработчик события есть код. Код может работать и без формы.
Этот _управляемый_ код даже без объекта, которому принадлежит, умудряется работать :)

Nord777 писал(а):В твоём случае ImageList принадлежит форме поэтому такая бодяга и происходит. Держи свои картинки в массиве или ресурсах, тогда не придется писать аж целую строку кода.
Да нету уже ни формы, ни её контролов. Осталось в живых только событие от мёртвого контрола - это прикольно даже :)

Ладно - я привыкну постепенно и к этому. Главное чтобы в конце концов не пришлось каждую строку _управляемого_ кода оформлять таким вот образом:

Код: Выделить всё
                Try
                        ...................
                Catch ex As Exception
                        Msgbox("От блин! Опять!")
                End Try

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 18.06.2007 (Пн) 1:11

Ты так перегибаешь палку от незнания или по приколу?
Если свойство формы Visible=False то это не означает что её не существует. Ты с дебагером умеешь обращаться? расширь немного свой кругозор. в процедуре btnQuit_MouseLeave поставь точку останова и помотри в окне Autos значения переменных(к ним же относится и форма и imagelist).
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Сообщение asharky » 19.06.2007 (Вт) 8:22

Nord777 писал(а):Ты с дебагером умеешь обращаться?
Пока нет.
Лучше, кстати, писать
Код: Выделить всё
If imglstCommandKey.Images.Empty = 0 Then Exit Sub
нежели
Код: Выделить всё
If imglstCommandKey.Images.Count = 0 Then Exit Sub


Me.Close() разве всего-лишь делает форму не видимой? Я думал она её уничтожает.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 19.06.2007 (Вт) 9:58

Во-первых, вместо

Код: Выделить всё
If imglstCommandKey.Images.Empty = 0 Then Exit Sub


надо писать

Код: Выделить всё
If Not imglstCommandKey.Images.Empty Then Exit Sub


А во-вторых не факт, что это лучше чем проверка Count на ноль.

Метод Close закрывает форму (т.е. уничтожаются все связанные с ней ресурсы, в том числе контролы), но отнюдь не уничтожает объект формы.
Весь мир матрица, а мы в нем потоки байтов!

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Сообщение asharky » 19.06.2007 (Вт) 12:22

Viper писал(а):Во-первых, вместо
Код: Выделить всё
If imglstCommandKey.Images.Empty = 0 Then Exit Sub

надо писать
Код: Выделить всё
If Not imglstCommandKey.Images.Empty Then Exit Sub

А во-вторых не факт, что это лучше чем проверка Count на ноль.


1. Это я опечатался :oops: Извините. В проге у меня конечно без "= 0 "
2. Почему "не факт, что лучше"? Есть какой-то скрытый смысл?

Viper писал(а):Метод Close закрывает форму (т.е. уничтожаются все связанные с ней ресурсы, в том числе контролы), но отнюдь не уничтожает объект формы.
Кажется до меня дошло - спасибо.

А в собственно классе сделать me=Nothing мы разумеется не можем :roll:

А если с Dispose() поиграться, то тоже ничего не получится? У меня не получилось в общем.

Сделал так в итоге:

Код: Выделить всё
   Private Sub btnQuit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
   Handles btnQuit.Click
      Dim response As New MsgBoxResult
      response = MsgBox("Завершить программу? Вы уверены?", MsgBoxStyle.YesNo, "Завершение программы")
      If response = MsgBoxResult.Yes Then
         Me.Close()
      End If
   End Sub


Код: Выделить всё
   Private Sub btnQuit_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) _
   Handles btnQuit.MouseLeave
      Me.btnQuit.Image = Me.imglstCommandKey.Images(0)
   End Sub


И волки, и овцы :) Нажатие на кнопку выхода из программы вызывает MsgBox с подтверждение и злосчастное событие MouseLeave. Но оно отрабатывается до уничтожения контролов и формы и не вызывает ошибки.

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Сообщение iGrok » 19.06.2007 (Вт) 14:27

Угу.. Но в таком ракурсе, исключение ты не обрабатываешь. Соответственно, теоретически оно все равно может возникнуть, и сообщение об ошибке таки вылезет.

Я не понял, что тебя конкретно не устраивает в штатном способе обработки ислючений???
label:
cli
jmp label

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 19.06.2007 (Вт) 15:09

asharky писал(а):2. Почему "не факт, что лучше"? Есть какой-то скрытый смысл?


А скорее всего свойство Empty реализуется путем сравнения числа элементов с нулем, поэтому, если сразу сравнивать Count с нулем, то можем чуть ускорить процесс.


З.Ы. И да, почто не нравится ловить исключение то? Вполне кошерный метод обработки
Весь мир матрица, а мы в нем потоки байтов!

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Сообщение asharky » 19.06.2007 (Вт) 15:18

iGrok писал(а):Угу.. Но в таком ракурсе, исключение ты не обрабатываешь. Соответственно, теоретически оно все равно может возникнуть, и сообщение об ошибке таки вылезет.
Ну да, возникнет. Если позле нажатия на ЩК в msgbox'е мышой со скоростью света шурануть на кнопку выхода формы.

iGrok писал(а):Я не понял, что тебя конкретно не устраивает в штатном способе обработки исключений???
Не уютно от того, что логика порушена: дали команду на уничтожение объекта, а он ещё рыпается после выстрела и какие-то события инициирует. Получается, что надо контрольный делать - это напрягает :)

Получается, что объекты в .NET имеют некоторую "инерцию" (не знаю как правильно назвать). И на эту "инерцию" надо закладываться плишней проверкой на исключение.

В даннном, частном, случае - нет проблем. Но где ещё выскочит подобное - кто знает? Я вот тут с файлами на запись работал - так их не достаточно закрыть, их флешить перед закрытием надо оказывается. Тому кто привык подобное делать, наверное и невдомёк, что по умолчанию хорошая и "правильная" система перед закрытием должна по-уму подобное сама проделывать. Чай .NET не ассемблер, а среда высочайшего уровня. А такие огрехи встречаются :(

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 19.06.2007 (Вт) 15:34

При закрытии файла все его буферы будут записаны на диск, посему перед закрытием Flush вызывать нет никакой необходимости.
Весь мир матрица, а мы в нем потоки байтов!

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Сообщение asharky » 19.06.2007 (Вт) 16:40

Viper писал(а):При закрытии файла все его буферы будут записаны на диск, посему перед закрытием Flush вызывать нет никакой необходимости.
Не факт:

Код: Выделить всё
While (Not m_streamBuyersRead.EndOfStream)
   m_stringTemp = m_streamBuyersRead.ReadLine()
   If m_stringTemp.StartsWith("8320") Then
      m_stringTemp = m_stringTemp.Trim()
      m_stringArray = m_stringTemp.Split(Chr(9))
      m_dataSetCustomers.Tables("Customer").Rows.Add
      (m_stringArray(0), m_stringArray(1), m_stringArray(2), CInt(m_stringArray(3)))
      Dim i As Integer
      For i = 0 To m_stringArray.Length - 1
         m_streamNewBuyersSave.WriteLine(m_stringArray(i))
      Next

   End If

End While
m_streamNewBuyersSave.Flush()
m_streamNewBuyersSave.Close()


Без флеширования файло из потока недописывается на диск в данном кусочке кода. Опять наверное "инерция" :)

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Сообщение Nord777 » 19.06.2007 (Вт) 23:38

Viper писал(а):А скорее всего свойство Empty реализуется путем сравнения числа элементов с нулем, поэтому, если сразу сравнивать Count с нулем, то можем чуть ускорить процесс.

так и есть:
Код: Выделить всё
Public ReadOnly Property Empty As Boolean
    Get
        Return (Me.Count Is &H0)
    End Get
End Property


Nord777 писал(а):Ты с дебагером умеешь обращаться?
asharky писал(а):Пока нет.



1) Ставишь точку останова на нужную тебе строку (просто щелкни мышью в том же месте где нарисован курсор)
красный кружок означает точку останова. В этом месте исполнение программы будет приостанавливаться и ты сможешь наблюдать значения переменных
Изображение



2) Запусти программу на выполнение и дождись когда она остановится на точке останова.Если окно "Autos" или "Locals" отсутствует, то открой его:
Изображение



3) Теперь ты можешь просмотреть значения переменных так....
Изображение



или так...
Изображение
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

asharky
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 162
Зарегистрирован: 22.06.2004 (Вт) 0:39
Откуда: Батоны-ларьки-поребрики...

Сообщение asharky » 19.06.2007 (Вт) 23:43

Nord777 писал(а):...1) Ставишь точку останова на нужную тебе строку...
Встроенным-то умею конечно. Я думал речь о Microsoft CLR Debugger 2005 шла. Который из SDK v.2.0. Им - слабо пока. Но научусь :)

Nord777. Ты так детально всё расписал в отношении использования встроенного дебаггера, что мне даже не ловко как-то. Чтобы труд не пропал, может быть модераторы отделят твой пост в отдельную тему "Использование встроенного дебаггера для просмотра текущего значения переменных", а?


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 115

    TopList