2010-09-21 3 views
-1

У меня есть библиотека пользовательского элемента управления. Теперь есть контроль, который выглядит как панель, и когда она открывается, я хочу, чтобы оживить его вертикальный растет, как это:.net 2010 вызов DoEvents (да, я хочу) из встроенной библиотеки управления

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, но не может находиться внутри библиотеки.

Как я могу это сделать, не утопая в глубинах нитей?

+0

К слову, 0,5 пиксела приращений в бессмыслице. –

ответ

-1

Это то, что я нашел: таймер, даже с быстрыми интервалами, очень медленный. Я не знаю, почему, но анимация очень нервничает с таймером.Упрощенный код:

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 

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

Любые подсказки?

2

Возможно, вам просто не хватает ссылки на (или импорт) System.Windows.Forms? DoEvents - это статический метод Application, поэтому вы также можете позвонить ему из библиотеки.

Imports System.Windows.Forms 

... 

    Application.DoEvents() 

(Вы уже, кажется, знают, что с помощью DoEvents это опасная вещь, так что я буду показывать обычную лекцию здесь.)

+0

Я могу назвать DoEvents, но он не показывает анимацию. – vulkanino

+0

@vulkanino: И тот же код * работает, когда он находится в проекте WinForm? – Heinzi

+0

Да, это то, что происходит. – vulkanino

2

Да, вы должны быть в состоянии назвать

System.Windows.Forms.Application.DoEvents() 

Из вашей библиотеки кода. Кажется, вы понимаете, что DoEvents - это плохая идея, поэтому я не уверен, почему вы ее называете. Я предполагаю, что у вас это есть внутри переопределения, например OnVisibleChanged или OnPaint, - если это так, вы, скорее всего, не получите результаты, которые вы после этого, так как обновление контроля будет приостановлено во время этих операций.

Возможно, вам захочется создать таймер с одним тиком, а по тику увеличить высоту элемента управления - отключить таймер при достижении конечной высоты или запланировать еще один тик, если нет. Или создайте таймер и поместите в него свой цикл в каждом тике. Убедитесь, что вы знаете о InvokeRequired и перекрестных вызовах в зависимости от того, какой тип таймера вы используете.

1

Неспособность воспроизвести.

Просто протестирован с простой настройкой UserControl в сборке.

Таймер на MainForm продолжает тикать, когда UC вызывает DoEvents() в цикле.

Итак: Посмотрите еще раз на свою проблему, это не то место, где вы думаете.

+0

Таймер тикает, но анимация очень медленная с этим. Вот почему я решил использовать цикл и DoEvents. – vulkanino

+1

Я использовал таймер на основной форме, чтобы показать, что DoEvents в lib работает. Но DoWvents по-прежнему очень плохая идея. –

3

Извините, но абсолютно безопасно использовать DoEvents здесь. Ничего хорошего не произойдет, когда пользователь закрывает форму во время анимации. Это приведет к сбою программы с помощью исключения ObjectDisposed. Для обеспечения безопасности DoEvents требуется установить для свойства Enable формы значение false, чтобы пользователь не мог случайно вызвать ошибки вроде этого. Элемент управления не может разумно установить форму Включено свойство false, особенно не для анимации.

Обходной путь достаточно прост, просто используйте таймер с интервалом 15 мс. Достаточно быстрый, чтобы анимация выглядела гладко. Вы найдете пример кода, который делает это в моем ответе в this thread.

+0

Это неправда. Во время анимации пользователь не может закрыть форму. Вход пользователя заблокирован. Таймер работает, но он очень медленный. – vulkanino

+2

Эмм, теперь он заблокирован, да. Но не тогда, когда вы начинаете звонить DoEvents. –

+2

О, и 15 мсек * не * медленно. Это 60 обновлений в секунду, что в два раза быстрее, чем то, что вы видите при просмотре фильма. Он выглядит медленным, потому что ваш прирост в 0,5 пикселя слишком мал. Сделайте это 5. –

0

В вашем оригинальном для петли месте Me.Refresh, где вы хотели назвать события.

For h As Single = 0 To finalHeight Step 0.5 
    Me.Height = CInt(h) 
    Me.refresh 
Next 
Me.Height = finalHeight 

 Смежные вопросы

  • Нет связанных вопросов^_^