Анимированный GIF на кнопку останавливается после перемещения (перерисовки) формы - PullRequest
2 голосов
/ 07 мая 2009

У меня есть анимированный GIF, помещенный на кнопку. Это анимация нормально (в большинстве случаев: P), но когда окна перерисовываются (перерисовываются) анимация останавливается Я пытался обновить кнопку (button.Refresh ()) при обработке события Paint, но это не решило проблему. \

Кто-нибудь знает, как это исправить?

1 Ответ

3 голосов
/ 02 сентября 2009

Возможно, я ошибаюсь, но я думаю, что проблема в том, что он перестает анимироваться не тогда, когда форма перерисовывается, а когда анимированный объект скрыт другим окном. Это намеренное поведение; ошибка в том, что в Windows Vista и Windows 7 дисплей составлен, поэтому, несмотря на то, что окно было «скрыто», оно никогда не было действительно скрыто, и оно никогда не получит сообщения рисования, когда оно не скрыто, что вызовет анимацию.

Эта ошибка влияет на любой элемент управления, производный от ButtonBase, с анимированным объектом.

Проблема заключается в функции Control.IsWindowObscured. Это вернет истину. Вы можете увидеть в файле ButtonBase.cs, в System.Windows.Forms.ButtonBase.OnFrameChanged, в самом конце есть строка кода, которая говорит:

if (IsWindowObscured) {
 StopAnimate();
 return;
}

и в этом заключается проблема.

FYI, OnFrameChanged вызывается из потока ImageAnimator. Это обратный вызов, указанный в ImageAnimator.Animate (изображение, обработчик событий). ButtonBase устанавливает это в закрытой void Animate (bool animate) функции. Поток ImageAnimator опрашивает каждые 50 мс и проверяет, нужен ли новый кадр для какого-либо из изображений, которые он отслеживает; если это так, он устанавливает флаг, чтобы сделать элемент управления недействительным и нарисовать новый кадр.

Поскольку это недоступно для нас, я не думаю, что мы многое можем с этим поделать. В качестве обходного пути я внедрил в форму таймер, который делает недействительным элемент управления каждые 500 мс, поэтому он будет перезапускать его, если он ранее был остановлен. Это довольно раздражает, что мы не можем переопределить или даже получить к нему доступ. Боюсь, единственное решение - взломать выше, или создать или использовать элемент управления, созданный вами или третьей стороной.

Для пояснения - это проблема только в Windows Vista или Windows 7 с использованием композиции рабочего стола. Проблема в том, что окна никогда не бывают затененными, как если бы они не использовали композицию на рабочем столе Они всегда буферизируются оконным менеджером. (В Windows 2000+ есть специальные многослойные окна, но пока игнорируйте это). Ранее части окна были недоступны, если их не было на экране или они были скрыты другим окном. Когда они возвращаются в поле зрения, изменяя фокус или положение и т. Д., Система уведомляет эту область о перекраске. Однако при использовании композиции рабочего стола перекрашивание никогда не требуется, поскольку фактическое содержимое окна буферизуется в другом месте. Вот почему окно предварительного просмотра работает на панели задач, а Flip-3d, например. Побочным эффектом является то, что код, который ожидает получить сообщение рисования, когда оно снова становится видимым после скрытия, завершится ошибкой. Код ButtonBase ожидает получения сообщения рисования, как только оно вернется в поле зрения, что снова запустит анимацию. И поэтому эта оптимизация стала ошибкой.

О проблеме следует сообщать в Microsoft Connect, хотя она вряд ли будет решена.

...