Чтение онлайн

на главную

Жанры

Шрифт:
...

Листинг 7.10.

Определение характеристик мультимедиа-таймера

//Получение максимального периода таймера (мс)

function timeGetMaxPeriod: Cardinal;

var

time: TTimeCaps;

begin

timeGetDevCaps(Addr(time), SizeOf(time));

timeGetMaxPeriod := time.wPeriodMax;

end;

//Получение минимального периода таймера (мс)

function timeGetMinPeriod: DWORD;

var

time: TTimeCaps;

begin

timeGetDevCaps(Addr(time), SizeOf(time));

timeGetMinPeriod := time.wPeriodMin;

end;

Итак,

мы знаем, как получать параметры таймера. Но было сказано, что его точность можно регулировать. Делается это при помощи функций timeBeginPeriod и timeEndPeriod.

• Первая функция вызывается для установления минимальной точности таймера, которая устраивает приложение. Функция timeBeginPeriod принимает значение требуемой точности таймера в миллисекундах, возвращает TIMERR_NOERROR в случае успеха либо Т IMERR_NOCANDO, если требуемая точность не может быть обеспечена.

• Вторая функция восстанавливает точность таймера такой, какой она была до вызова функции timeBeginPeriod. В функцию timeEndPeriod должно передаваться то же значение, что и в функцию timeBeginPeriod.

В листинге 7.11 показано использование функци и timeBeginPeriod, атакже timeEndPeriod (реализованы функции-оболочки). При пользовании функциями из листинга 7.11 нужно помнить, что после вызова timeSetTimerPeriod и проведения измерения обязательно должна быть вызвана timeRestoreTimerPeriod. Функция timeSetTimerPeriod сохраняет значение установленной точности таймера в глобальной переменной lastPeriod, чтобы можно было не заботиться о сохранении этого значения в коде, использующем таймер.

...

Листинг 7.11. Функции изменения точности таймера

Var lastPeriod: Cardinal;

//Установка периода таймера (мс) перед началом измерения

function timeSetTimerPeriod(period: Cardinal): Boolean;

begin

if timeBeginPeriod(period) = TIMERR_NOERROR then

begin

//Сохраним значение для восстановления состояния таймера

lastPeriod := period;

timeSetTimerPeriod := True;

end

else

//Неудача

timeSetTimerPeriod := False;

end;

//Восстановление периода таймера (обязательно)

function timeRestoreTimerPeriod: Boolean;

begin

if timeEndPeriod(lastPeriod) = TIMERR_NOERROR then

timeRestoreTimerPeriod := True

else

timeRestoreTimerPeriod := False;

end;

Теперь, после долгого рассмотрения особенностей настройки мультимедиа-таймера, приведем пример его использования для измерения времени выполнения простейшего отрезка программы (листинг 7.12).

...

Листинг 7.12.

Измерение времени выполнения отрезка программы

procedure TForm1.cmbTimeGoClick(Sender: TObject);

var

summ, arg, maxVal: Int64;

startTime, endTime: Cardinal;

begin

txtTimeResult.Text := \'Измерение…\

Refresh;

maxVal := StrToInt(txtTimeMaxVal.Text);

//Устанавливаем маскимальную точность таймера

timeSetTimerPeriod(timeGetMinPeriod);

startTime := timeGetTime; //Начальный момент времени

//Суммируем 64-битные числа

//(как раз и измеряем время его выполнения)

summ := 0;

arg := 1;

while (arg <= maxVal) do

begin

Inc(summ, arg);

Inc(arg);

end;

endTime := timeGetTime; //Конечный

момент времени

//Восстанавливаем период таймера

timeRestoreTimerPeriod;

//Время выполнения операций (мс)

txtTimeResult.Text := IntToStr(endTime – startTime);

end;

Создание программного таймера высокой точности

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

Теперь уясним, что же за программный таймер мы создаем и чем он отличается от компонента Timer, помещаемого на форму. А отличается наш таймер, кроме высокой точности, тем, что его не нужно привязывать к окну (форме): при срабатывании стандартного компонента Timer окну, за которым он закреплен, посылается сообщение WM_TIMER. Создаваемый же нами таймер работает по-другому, что удобнее рассмотреть на примере.

...

timerID := timeSetEvent

(

StrToInt(txtTimeInterval.Text), //Интервал между

//срабатываниями таймера

timeGetMinPeriod, //Точность таймера

TimerProc, //Адрес процедуры, вызываемой при каждом

//срабатывании таймера

0, //Параметр, передаваемый в процедуру

//обратного вызова

TIME_CALLBACK_FUNCTION or TIME_PERIODIC //Тип таймера

);

В приведенном выше отрывке программы с помощью функции timeSetEvent происходит регистрация и запоминание адреса процедуры TimerProc, вызываемой периодически при срабатываниях таймера. При успешном создании таймера функция timeSetEvent возвращает ненулевое значение – идентификатор созданного таймера. Оно может использоваться в дальнейшем для определения, какой именно таймер сработал. Значение, возвращенное функцией timeSetEvent, также необходимо при удалении таймера:

...

timeKillEvent(timerlD);

Функция timeKillEvent возвращает целочисленное значение:

• TIMERR_NOERROR – если ее вызов завершился успешно;

• MMSYSERR_INVALPARAM – если таймера, заданного параметром функции, не существует.

Теперь о процедуре, адрес которой мы передаем в функцию timeSetEvent. В нашем примере она выглядит следующим образом (листинг 7.13).

...

Листинг 7.13.

Процедура, вызываемая при срабатывании таймера

procedure TimerProc(uTimerID, uMessage: UINT; dwUser, dw1, dw2:

DWORD) stdcall;

begin

//Добавляем текущее значение времени в список (чтобы была

//видна разница между моментами вызова этой процедуры)

Form1.lstTimes.Items.Add(IntToStr(timeGetTime));

end;

Естественно, действия, выполняемые процедурой TimerProc, могут быть самыми различными. В нашем случае происходит заполнение списка (List) значениями счетчика «тиков» таймера на момент вызова процедуры (рис. 7.5).

Поделиться:
Популярные книги

Не грози Дубровскому! Том VIII

Панарин Антон
8. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том VIII

Para bellum

Ланцов Михаил Алексеевич
4. Фрунзе
Фантастика:
попаданцы
альтернативная история
6.60
рейтинг книги
Para bellum

Архонт

Прокофьев Роман Юрьевич
5. Стеллар
Фантастика:
боевая фантастика
рпг
7.80
рейтинг книги
Архонт

Сильнейший ученик. Том 2

Ткачев Андрей Юрьевич
2. Пробуждение крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сильнейший ученик. Том 2

Измена. Ребёнок от бывшего мужа

Стар Дана
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Ребёнок от бывшего мужа

Real-Rpg. Город гоблинов

Жгулёв Пётр Николаевич
1. Real-Rpg
Фантастика:
фэнтези
7.81
рейтинг книги
Real-Rpg. Город гоблинов

Хозяйка Междуречья

Алеева Елена
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Хозяйка Междуречья

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Эйгор. В потёмках

Кронос Александр
1. Эйгор
Фантастика:
боевая фантастика
7.00
рейтинг книги
Эйгор. В потёмках

Идеальный мир для Лекаря 3

Сапфир Олег
3. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 3

Кодекс Крови. Книга III

Борзых М.
3. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга III

Вернуть невесту. Ловушка для попаданки 2

Ардова Алиса
2. Вернуть невесту
Любовные романы:
любовно-фантастические романы
7.88
рейтинг книги
Вернуть невесту. Ловушка для попаданки 2

Черный Маг Императора 7 (CИ)

Герда Александр
7. Черный маг императора
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 7 (CИ)

Удобная жена

Волкова Виктория Борисовна
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Удобная жена