Таймер высокой точности Таймер высокой точности
Теория |
*
| *
|
| |
Стандартный таймер позволяет отсчитывать интервалы с точностью
порядка 50-60 мс. Однако существует быстродействующий таймер,
который применяется для мультимедийных приложений. Для его
использования необходимо включить в uses модуль mmsystem:
Функция имеет вид:
MMRESULT timeSetEvent(
UINT uDelay, // Задержка в мс
UINT uResolution, // Разрешающая способность
LPTIMECALLBACK lpTimeProc, // Указатель на процедуру-обработчик
DWORD dwUser, // Параметр разработчика
UINT fuEvent // Тип события
);
Функция имеет седеющие параметры (я их кратко комментировал в описании функции)
- uDelay - задержка в мс
- uResolution - разрешающая способность (0-максимально доступная для
данного ПК), задается в мс.
- lpTimeProc - указатель на процедуру, которая будет вызываться
по истечения заданного интервала времени. Процедура должна иметь вид
procedure MyTimerCallBackProg(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD); stdcall;
begin
;
end;
Следует обратить внимание на то, что функция использует
соглашение о передаче пераметров stdcall
- dwUser - Параметр пользователя. Этот параметр передается в
обработчик lpTimeProc и может использоваться по усмотрению
программиста
- fuEvent - тип таймера. Возможно два значения:
- TIME_ONESHOT - обработчик таймера вызывается один раз, по истечении
заданного в uDelay времени
- TIME_PERIODIC - обработчик таймера вызывается периодически, период
задается значением uDelay
При успешном создании таймера возвращается его идентификатор, в
случае ошибки возвращается NULL. После завершения работы с
таймером нуобходимо удалить его при помощи функции timeKillEvent:
MMRESULT timeKillEvent(
UINT uTimerID
);
Функция получает единственный параметр - номер, присвоенный
таймеру при его создания при помощи timeSetEvent. Функция возвращает
TIMERR_NOERROR при нормальном удалении таймера и MMSYSERR_INVALPARAM
в случает указания кода несуществующего таймера.
Пример реализации |
*
| *
|
| |
Рассмотрим учебный пример, демонстрирующий особенности работы
обычного таймер и мультимедиа-таймера:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, mmsystem, ExtCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Timer1: TTimer;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
MMTimer1 : integer; // Код мультимедийного таймера
end;
var
Form1: TForm1;
Cnt1, Cnt2 : integer;
implementation
{$R *.dfm}
procedure MyTimerCallBackProg(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD); stdcall;
begin
Inc(Cnt1); // Счетчик срабатывания мультимедиа таймера
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
MMTimer1 := timeSetEvent(1,1,@MyTimerCallBackProg,100,TIME_PERIODIC);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
// Удаление таймера при завершении программы
timeKillEvent(MMTimer1);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
inc(Cnt2); // Счетчик срабатывания обычного таймера
end;
procedure TForm1.Button1Click(Sender: TObject);
var
t : integer;
begin
Memo1.Lines.Clear;
Memo1.Lines.Add('Опыт 1 - Sleep на 5 секунд');
Cnt1 := 0;
Cnt2 := 0;
Sleep(5000);
Memo1.Lines.Add('Число срабатываний мультимедиа таймера = '+IntToStr(Cnt1));
Memo1.Lines.Add('Число срабатываний TTimer c Interval=1 = '+IntToStr(Cnt2));
Memo1.Lines.Add('Опыт 2 - Цикл ожидания с Application.ProcessMessages');
Cnt1 := 0;
Cnt2 := 0;
t := GetTickCount;
while GetTickCount - t < 5000 do
Application.ProcessMessages;
Memo1.Lines.Add('Число срабатываний мультимедиа таймера = '+IntToStr(Cnt1));
Memo1.Lines.Add('Число срабатываний TTimer c Interval=1 = '+IntToStr(Cnt2));
end;
end.
На форме необходимо разместить Memo1 типа TMemo и таймер типа
TTimer с интервалом 1 и обрабочтчиком Timer1Timer.
В этом примере очень хорошо видно, что на время Sleep обычный таймер
не действует (т.к. он основан на сообщениях). Кроме того, очень
наглядна разница в точности - мультимедийный таймер срабатывает примерно
5000 раз за 5 секунд (как и положено по его настройке). Обычный
таймер в первом опыте не срабатывает вообще, во втором опыте
срабатывает примерно 320 раз (т.е. примерно один раз в 15 мс)
© Зайцев Олег, "Программирование на Delphi - обмен опытом" 1999-2004. При использовании любых материалов данного сайта
необходимо указывать источник информации. Дата обновления: 22.11.2004. Сайт размещен на хостинге AGAVA - Хостинг от AGAVA.ru