.net 2010 вызывает DoEvents (да, я хочу) из библиотеки пользовательских элементов управления - PullRequest
0 голосов
/ 21 сентября 2010

У меня есть библиотека пользовательского элемента управления. Теперь есть элемент управления, который выглядит как панель, и когда он открывается, я хочу анимировать его вертикальный рост следующим образом:

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 ]

3 голосов
/ 21 сентября 2010

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

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

2 голосов
/ 21 сентября 2010

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

System.Windows.Forms.Application.DoEvents()

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

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

2 голосов
/ 21 сентября 2010

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

Imports System.Windows.Forms

...

    Application.DoEvents()

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

1 голос
/ 21 сентября 2010

Невозможно воспроизвести.

Только что протестировано с простой настройкой, UserControl в сборке.

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

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

0 голосов
/ 04 января 2012

В исходном цикле for поместите Me.Refresh туда, где вы хотели позвонить дофинам.

For h As Single = 0 To finalHeight Step 0.5
    Me.Height = CInt(h)
    Me.refresh
Next
Me.Height = finalHeight
0 голосов
/ 21 сентября 2010

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

 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 

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

Есть намеки?

...