Среда, 02.07.2025, 17:15
Приветствую Вас Гость

Soft by Warik

NEMO_CHAT
Категории раздела
Анекдот
Случайный анекдот:

Наши часики
Опрос
Какое время года Вам больше нравится?
Всего ответов: 24
Статистика
Rambler's Top100




Онлайн всего: 1
Гостей: 1
Пользователей: 0
Главная » Статьи » Win API [ Добавить статью ]

Работа с мультимедийным таймером на Win API

Мы уже знакомы с системным таймером, сегодня познакомимся с мультимедийным, основное отличие которого, более высокая скорость (точность) работы. Мультимедийный таймер способен работать с интервалом вплоть до 1 ms, в то время как, интервалы работы системного таймера больше, и зависят от версии ОС. Для Windows95/98 интервал составляет ~50 ms, в Windows2000/XP интервал может быть меньше (у меня он равен ~10 ms).

Сейчас мы убедимся в этом на примере, для чего создадим два таймера: системный и мультимедийный. Оба таймера будут показывать, сколько раз в секунду им удалось сработать.

Code
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). Такую же функцию будем использовать для работы с системным таймером. Посмотрим их описание.

Code
(* CallBack функция для системного таймера *)
procedure TimerProc( Wnd: HWND; uMsg: UINT; idEvent: UINT; dwTimer: UINT ); stdcall;

(* CallBack функция для мультимедийного таймера *)
procedure MMTimerProc( uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD ); stdcall;

Обратим внимание на то, что функция использует соглашение о передаче параметров stdcall.

Определим эти функции.

Code
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;

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

Перейдем к созданию таймеров.

Code
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 (обработчик таймера вызывается периодически).

Уничтожение таймеров выглядит следующим образом.

Code
KillTimer( Wnd, IDTimer1 );
timeKillEvent( MMTimerID );

Пара слов о работе этих таймеров. Системный таймер: Если обработчик таймера не успевает закончить все действия в установленный интервал, то последующие вызовы этого обработчика становятся в очередь. Это приводит к тому, что на разных компьютерах приложение работает с разной скоростью. Сама же CallBack функция вызывается в контексте основного потока. Мультимедийный таймер: Если обработчик таймера не успевает закончить все действия в установленный интервал, то последующие вызовы накапливаться не будут. Сама же CallBack функция вызывается в контексте отдельного потока.

На сегодня это все, удачи в программировании.

Источник: http://nemo-chat.3dn.ru

Категория: Win API | Добавил: Warik (23.02.2010)
Просмотров: 548 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Мини-профиль

Гость !



Гость, мы рады вас видеть. Пожалуйста зарегистрируйтесь или авторизуйтесь!
Друзья сайта