Статьи Королевства Дельфи

       

Введение в анимацию


Анимация заключается в последовательной смене картинок. При этом главная проблема - устранение мерцания изображения. В программе Canvas2 мерцание "резиновой" линии в целом незаметно, так как эта линия постоянно изменяет своё положение, а вот мерцание подложки, на которой нарисованы уже "впечатанные" в неё линии, было бы заметно, поэтому пришлось принимать специальные меры по её устранению.

Чтобы не было мерцания при обновлении изображения, необходимо выполнение двух условий:

  • Быстрая смена одного изображения другим
  • Отсутствие между старым и новым изображением промежуточных полустёртых изображений

Максимальную скорость вывода при использовании средств GDI даёт вывод изображения на поверхность растра (bitmap) с последующим перенесением на экран. Этим обеспечивается то, что все элементы рисунка выводятся на экран одновременно, а не по очереди, что позволяет избежать промежуточных изображений. Поэтому программа Canvas2 хранит растр, на котором отображаются уже завершённые кривые, и при обработке события OnPaint рисует растр, а сверху - редактируемую в данный момент кривую с дополнительными элементами, облегчающими редактирование. Тем не менее, это не устраняет мерцание полностью, если для обновления окна использовать метод TWinControl.Refresh или TWinControl.Invalidate. Это связано с особенностями рисования окон в Windows и с тем, как VCL использует эти особенности.

Для перерисовки сначала с помощью функций InvalidateRect или InvalidateRgn отмечается область окна, нуждающаяся в обновлении. Можно последовательно отметить несколько областей - система будет добавлять новую область к уже существующей. Затем с помощью функции UpdateWindow в очередь сообщений помещается WM_Paint. Рисование окна происходит при обработке этого сообщения. Для начала рисования вызывается функция BeginPaint. Эта функция анализирует область, нуждающуюся в обновлении, и, если при вызове функций InvalidateRect/Rgn был установлен флаг обновления фона, посылает окну сообщение WM_EraseBknd. В ответ на это сообщение окно закрашивает свою клиентскую часть заданной кистью. В частности, для форм Delphi это будет сплошная кисть с цветом, определяемым свойством Color формы. Поэтому сначала будет стёрто старое изображение, и лишь затем будет нарисовано новое. Это приводит к появлению мерцания.

Существует три способа избавиться от мерцания:

  • Не указывать флаг обновления фона при вызове InvalidateRect(Rgn)
  • Перекрыть обработчик WM_EraseBkgnd и ничего не делать при получении этого сообщения
  • Обновлять окно напрямую, без сообщения WM_Paint.
В Delphi самым простым является третий способ: достаточно вызвать процедуру обработки OnPaint напрямую. Для реализации первого способа придётся вручную вызывать функцию API InvalidateRect, потому что TWinControl.Invalidate не позволяет сбрасывать флаг обновления фона. Второй способ не очень удобен, если анимированная картинка занимает не всё окно. Поэтому в программе Canvas2 выбран третий способ.



Содержание раздела