Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа №22.pdf
Скачиваний:
30
Добавлен:
16.03.2015
Размер:
1.63 Mб
Скачать

Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»

end;

Запустите программу.

Создание анимации

Существует несколько различных способов для создания анимации в Delphi. Рассмотрим некоторые из них.

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

Осуществить буферизованный вывод на экран, для компонентов наследников класса TWinControl, можно установив значение свойства DoubleBuffered равным True. Это свойство доступно только на этапе прогона программы. Для компонентов не являющихся наследниками TWinControl двойную буферизацию осуществляют с помощью следующего алгоритма:

создается растр (класс TBitmap);

с помощью свойства Canvas класса TBitmap создается изображение на холсте растра;

далее содержимое растра с помощью методов Draw или CopyRect копируется на канву формы или какого-либо другого компонента;

параметры выводимого изображения изменяются и выше перечисленные операции повторяются.

Рассмотрим пример создания анимированного изображения на примере программы часов со стрелочным циферблатом.

Создайте новый проект. На форму frmClock поместите компонент TTimer (Timer). В секцию public формы frmClock поместите следующие строки

HourArrow:real;

//угол поворота часовой стрелки

MinArrow:real;

//угол

поворота

минутной стрелки

SecArrow:real;

//угол

поворота

секундной стрелки

r:Integer;

//радиус циферблата

Поместите метод ClockPaint в эту же секцию

//рисует часы на холсте ACanvas procedure ClockPaint(ACanvas:TCanvas);

Обратите внимание, что код рисования часов вынесен в отдельный метод. Именно такой подход наиболее эффективен при создании анимации. Также в качестве параметра в метод передается холст, на котором создается изображение. Это позволяет написать код для рисования на любом компоненте, имеющем свойство Canvas. Тело метода приведено ниже.

procedure TfrmClock.ClockPaint(ACanvas:TCanvas); var i, x0, y0, r1:Integer;

begin

//радиус внутренней окружности циферблата r1:=r-10;

with ACanvas do begin

//центр холста x0:=ClipRect.Right div 2; y0:=ClipRect.Bottom div 2;

Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»

//стираем фон

Brush.Color:=clWhite;

Pen.Color:=clBlack;

Pen.Width:=1;

FillRect(ClientRect);

//центр экрана

MoveTo(x0-10, y0); LineTo(x0+10, y0); MoveTo(x0, y0-10); LineTo(x0, y0+10);

//рисуем циферблат

Brush.Style:=bsClear; Ellipse(x0-r, y0-r, x0+r, y0+r);

Ellipse(x0-r1, y0-r1, x0+r1, y0+r1);

//отметки на циферблате for i:=0 to 11 do

begin

MoveTo(Trunc(x0+r1*cos(PI/6*i)), Trunc(y0+r1*sin(PI/6*i))); LineTo(Trunc(x0+r*cos(PI/6*i)), Trunc(y0+r*sin(PI/6*i)));

end;{for}

//секундная стрелка

MoveTo(x0, y0);

LineTo(Trunc(x0 + r*cos(SecArrow)), Trunc(y0 + r*sin(SecArrow)));

//минутная стрелка

MoveTo(x0, y0);

LineTo(Trunc(x0 + r*cos(MinArrow)), Trunc(y0 + r*sin(MinArrow)));

//часовая стрелка

Pen.Width:=3; MoveTo(x0, y0);

LineTo(Trunc(x0 + r1*cos(HourArrow)), Trunc(y0 + r1*sin(HourArrow)));

end;{with} end;{ClockPaint}

Создайте еще один метод.

//расчитывает текущее положение стрелок часов procedure ClockCalc;

В этом методе рассчитывается положение стрелок часов в зависимости от текущего времени. Тело метода приведено ниже.

procedure TfrmClock.ClockCalc; var Hour, Min, Sec, Msec:Word; begin

//получаем время в формате //часы, мин, сек, мс

DecodeTime(Time, //получаем текущее время

Hour, Min, Sec, Msec);

//рассчитываем положение стрелок

SecArrow:=2*PI/60*Sec - Pi/2;

MinArrow:=2*PI/60*Min - PI/2; HourArrow:=2*PI/12*Hour + PI/6*(Min/60) - PI/2;

Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»

end;{ClockCalc}

Создайте обработчики событий OnPaint и OnCreate.

procedure TfrmClock.FormCreate(Sender: TObject); begin

r:=100;

DoubleBuffered:=True; //включаем двойную буферизацию ClockCalc; //расчет положения стрелок end;{FormCreate}

procedure TfrmClock.FormPaint(Sender: TObject); begin

ClockPaint(Canvas); //прорисовка часов end;{FormPaint}

Запустите программу. Примерный вид экрана программы приведен на рисунке 2.

Рисунок 2 – Вид окна программы часы

Пока часы не работают. Необходимо создать обработчик OnTimer для таймера (Timer). Обработчик события OnTimer приведен ниже.

procedure TfrmClock.TimerTimer(Sender: TObject); begin

ClockCalc; //расчет положения стрелок //перерисовать окно

InvalidateRect(Handle, nil, False); end;

Подробнее рассмотрим функцию InvalidateRect, которая имеет следующий синтаксис

function InvalidateRect(hWnd: HWND; lpRect: PRect; bErase: Boolean): Boolean;

где hWnd – дескриптор окна, подлежащего перерисовке;

lpRect – указатель на структуру TRect, область окна подлежащая перерисовке. Перерисовывается всё окно, если значение параметра равно nil;

bErase – если True, то перед перерисовкой окна перерисовывается его фон, иначе фон не перерисовывается.

Эта функция посылает Windows сообщение о необходимости перерисовать окно имеющее дескриптор (hWnd) или его часть если параметр lpRect отличен от nil. Если

Лабораторные работы по информатике для специальности «Моделирование и исследование операций в организационно-технических системах»

параметр bErase имеет значение True то фон окна стирается (для этого обрабатывается специальное событие), иначе не стирается.

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

Таким образом, после вызова функции InvalidateRect, Windows после обработки всех остальных сообщений посылает в окно, дескриптор которого указан в параметре HWnd, сообщение WM_Paint, которое вызывает событие OnPaint формы, что приводит к ее перерисовке.

Запустите программу, убедитесь, что часы отображают текущее время.

При изменении размеров окна размер циферблата часов не изменяется. Для того, чтобы циферблат часов при изменении размеров окна изменял свои размеры заполняя все окно необходимо добавить в форму обработчик события OnResize для формы.

procedure TfrmClock.FormResize(Sender: TObject); begin

//рассчитываем радиус циферблата

if ClientWidth>ClientHeight then r:=ClientHeight div 2-10 else r:=ClientWidth div 2-10;

//перерисовать окно

InvalidateRect(Handle, nil, False); end;{FormResize}

Теперь из тела обработчика события OnCreate можно удалить строку r:=10 т.к. она теперь не нужна.

Запустите программу, попробуйте изменить размер окна, убедитесь в том, что программа работает правильно.

В примере приведенном выше для двойной буферизации анимированного изображения использовалось свойство DoubleBuffered компонента TWinControl. Рассмотрим другой способ осуществления двойной буферизации при выводе анимированных изображений.

Создайте копию проекта приведенного выше. В качестве буфера будем использовать растр, который представлен классом TBitmap. Добавьте в секцию public формы следующую строку

Buffer:TBitmap; //буфер изображения

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

procedure TfrmClock.FormCreate(Sender: TObject); begin

Buffer:=TBitmap.Create; //создаем буфер изображений

ClockCalc; //расчет положения стрелок end;{FormCreate}

После окончания работы необходимо удалить буфер.

procedure TfrmClock.FormDestroy(Sender: TObject); begin

Buffer.Free; //удаляем буфер end;{FormDestroy}