.net 2010 Вызов Doevents (да, я хочу) изнутри пользовательской библиотеки управления
-
04-10-2019 - |
Вопрос
У меня есть библиотека пользовательского контроля. Теперь есть контроль, который выглядит как панель, и когда она открывается, я хочу оживить его вертикальные, как это:
For h As Single = 0 To finalHeight Step 0.5
Me.Height = CInt(h)
' HERE I WANT TO CALL DoEvents'
Next
Me.Height = finalHeight
Если я не называю Doevents в петле, тогда анимация не отображается, я получаю только окончательную высоту без визуальной обратной связи по пути.
Я могу назвать DoEvents изнутри моего главного проекта WinForm, но не могу внутри библиотеки.
Как я могу это сделать, не тонув в воду глубоких нитей?
Решение 6
Это то, что я нашел: таймер, даже с быстрыми интервалами, это действительно медленно. Я не знаю почему, но анимация очень крутится с таймером. Упрощенный код:
rolex = New Timer()
rolex.Interval = 150
AddHandler rolex.Tick,
Sub(sender As Object, e As EventArgs)
Me.Height += 5
If Me.Height < finalHeight Then Exit Sub
rolex.Stop()
rolex = Nothing
Me.Height = finalHeight
End Sub
rolex.Start()
Без таймера я использую цикл:
For i As Single = 0 To finalHeight Step 0.5
Height = CInt(i)
Application.DoEvents()
Next
Height = finalHeight
Это работает сейчас, но проблема в том, что скорость анимации слишком сильно зависит от машины, где выполняется петля. По этой причине я хотел бы использовать таймер, но, как я уже сказал, это слишком медленно.
Любые подсказки?
Другие советы
Извините, но совершенно невозможно сделать использование DoEvents Safe здесь. Ничего хорошего не произойдет, когда пользователь закрывает форму, пока ваша анимация идет. Он будет разорвать программу с помощью ObjectDisposed исключением. Создание DoEvents Safe требует установки внутреннего свойства формы для False, чтобы пользователь не мог случайно привести к тому, что Mishaps подобно. Управление не может разумно установить Форма Включено свойство на ложь, особенно не для анимации.
Обходной путь достаточно прост, просто используйте таймер с интервалом 15 мсек. Достаточно быстро, чтобы анимация выглядела гладкой. Вы найдете пример код, который делает это в моем ответе в эта нить.
Может быть, вы просто пропустите ссылку на (или импорт) System.Windows.Forms
? DoEvents
является статическим методом Application
, Так что вы должны иметь возможность называть это из библиотеки.
Imports System.Windows.Forms
...
Application.DoEvents()
(Вы уже знаете, что использовать DoEvents
Это опасная вещь, поэтому я буду пропустить обычную лекцию здесь.)
Да, вы должны быть в состоянии позвонить
System.Windows.Forms.Application.DoEvents()
Изнутри вашей библиотеки кода. Похоже, вы понимаете, что DoEvents - плохая идея, поэтому я не уверен, почему вы его называете. Я предполагаю, что у вас есть это поместить внутри переопределения, такого как onvisibleChangeded, или OnPaint - если это так, вы, скорее всего, не получите результаты, которые вы последуете, поскольку контроль обновления будет приостановлен во время этих операций.
То, что вы, вероятно, хотите сделать, это создать таймер одним тиком, и на тике увеличить высоту контроля - отключите таймер, когда Finalheight достигнут или запланируйте еще один тик, если нет. Или создайте таймер и поместите свой приведенный цикл в нем на каждом тике. Убедитесь, что вы знаете о InvokeRequired
и перекрестные вызовы в зависимости от того, какой тип таймера вы используете.
Неспособность воспроизвести.
Просто проверено с простой настройкой, USERCONTROL в сборке.
Таймер в Mainform продолжает тикать, когда UC вызывает DoEvents () в цикле.
Так что: Посмотрите еще раз для своей проблемы, это не то, где вы думаете, что это так.
В вашем оригинале для петли, поместите Me.Refresh
где вы хотели назвать доверенно.
For h As Single = 0 To finalHeight Step 0.5
Me.Height = CInt(h)
Me.refresh
Next
Me.Height = finalHeight