:: MVP ::
|
|
:: RSS ::
|
|
|
Мы уже знакомы с системным таймером, сегодня познакомимся с мультимедийным, основное
отличие которого, более высокая скорость (точность) работы. Мультимедийный таймер
способен работать с интервалом вплоть до 1 ms, в то время как, интервалы работы
системного таймера больше, и зависят от версии ОС. Для Windows95/98 интервал
составляет ~50 ms, в Windows2000/XP интервал может быть меньше (у меня он равен ~10 ms).
Сейчас мы убедимся в этом на примере, для чего создадим два таймера: системный и
мультимедийный. Оба таймера будут показывать, сколько раз в секунду им удалось
сработать.
const
IDTimer1 = 1;
IDLabelTimer = 2;
IDLabelMMTimer = 3;
var
Wc: TWndClassEx;
Wnd: HWND;
Msg: TMsg;
LabelTimer: HWND;
LabelMMTimer: HWND;
TimerBegin: Cardinal;
TimerCount: Cardinal = 0;
TimerOld: Cardinal = 0;
MMTimerID: Cardinal;
MMTimerBegin: Cardinal;
MMTimerCount: Cardinal = 0;
MMTimerOld: Cardinal = 0;
|
В прошлом примере, для работы с системным таймером, нам приходилось обрабатывать
сообщение WM_TIMER. Однако системный таймер никаких сообщений не генерирует,
для работы с ним нужно использовать функцию обратного вызова (CallBack). Такую
же функцию будем использовать для работы с системным таймером. Посмотрим их описание.
(* CallBack функция для системного таймера *)
procedure TimerProc( Wnd: HWND; uMsg: UINT; idEvent: UINT; dwTimer: UINT ); stdcall;
(* CallBack функция для мультимедийного таймера *)
procedure MMTimerProc( uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD ); stdcall;
|
Обратим внимание на то, что функция использует соглашение о передаче параметров
stdcall.
Определим эти функции.
procedure TimerProc( Wnd: HWND; uMsg: UINT; idEvent: UINT; dwTimer: UINT ); stdcall;
var
tmpTimer: string;
tmpTimerCount: string;
begin
Inc( TimerCount );
Str( TimerOld, tmpTimer );
Str( TimerCount, tmpTimerCount );
SetWindowText( LabelTimer, PChar( 'Timer: ' + tmpTimerCount + ' [' + tmpTimer + ']' ) );
if GetTickCount - TimerBegin >= 1000 then
begin
TimerOld := TimerCount;
TimerBegin := GetTickCount;
TimerCount := 0;
end;
end;
procedure MMTimerProc( uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD ); stdcall;
var
tmpMMTimer: string;
tmpMMTimerCount: string;
begin
Inc( MMTimerCount );
Str( MMTimerOld, tmpMMTimer );
Str( MMTimerCount, tmpMMTimerCount );
SetWindowText( LabelMMTimer, PChar( 'MMTimer: ' + tmpMMTimerCount + ' [' + tmpMMTimer + ']' ) );
if GetTickCount - MMTimerBegin >= 1000 then
begin
MMTimerOld := MMTimerCount;
MMTimerBegin := GetTickCount;
MMTimerCount := 0;
end;
end;
|
Как видим, все просто. Каждый тик таймера мы увеличиваем на единицу
переменную, которая показывает, сколько уже раз сработал таймер. Каждую секунду
обнуляем счетчик, предварительно сохранив его значение (это значение мы будем
показывать всю следующую секунду).
Перейдем к созданию таймеров.
SetTimer( Wnd, IDTimer1, 1, @TimerProc );
TimerBegin := GetTickCount;
MMTimerID := timeSetEvent( 1, 2, @MMTimerProc, 0, TIME_PERIODIC );
MMTimerBegin := TimerBegin;
|
С созданием системного таймера мы уже знакомы. Единственное отличие от предыдущего
примера заключается в том, что в качестве последнего параметра мы вместо nil
передаем указатель на CallBack функцию. Сразу после его создания запоминаем
текущее время, от него начнем отсчет интервалов, длинной в секунду. Затем создаем
мультимедийный таймер, для чего воспользуемся функцией timeSetEvent. Рассмотрим ее
параметры. 1 - интервал таймера (в миллисекундах). 2 - разрешающая способность
(количество миллисекунд, ограничивающее время на отработку каждого тика таймера).
Если задать 0, точность будет максимальной. 3 - адрес CallBack функции. 4 -
Параметр пользователя. Этот параметр передается в обработчик lpFunction и может
использоваться по усмотрению программиста. 5 - одна из двух констант: TIME_ONESHOT
(обработчик таймера вызывается один раз) или TIME_PERIODIC (обработчик таймера
вызывается периодически).
Уничтожение таймеров выглядит следующим образом.
KillTimer( Wnd, IDTimer1 );
timeKillEvent( MMTimerID );
|
Пара слов о работе этих таймеров. Системный таймер: Если обработчик таймера не
успевает закончить все действия в установленный интервал, то последующие вызовы
этого обработчика становятся в очередь. Это приводит к тому, что на разных
компьютерах приложение работает с разной скоростью. Сама же CallBack функция
вызывается в контексте основного потока. Мультимедийный таймер: Если обработчик
таймера не успевает закончить все действия в установленный интервал, то
последующие вызовы накапливаться не будут. Сама же CallBack функция вызывается
в контексте отдельного потока.
На сегодня это все, удачи в программировании.
.: Пример к данной статье :.
|
При использовании материала - ссылка на сайт обязательна
|
|