Программирование на Delphi - обмен опытом / Таймер высокой точности

© Зайцев Олег 1998-2004
Лучшая портативная техника. Плееры Камеры Телефоны Компьютеры
Покупателям, пришедшим на www.porta.ru по этой ссылке - дополнительная скидка 1%
Железо | Система | WEB | Компоненты | Графика | Ссылки | Мультимедиа | Сети | Прочее | Реестр | Литература

Статистика

Таймер высокой точности

Рекомендую:
Главная страница \ Системное программирование \ Таймер высокой точности

  • Таймер высокой точности

    Таймер высокой точности

    Теория * * Задать вопрос Наверх
    Стандартный таймер позволяет отсчитывать интервалы с точностью порядка 50-60 мс. Однако существует быстродействующий таймер, который применяется для мультимедийных приложений. Для его использования необходимо включить в uses модуль mmsystem:

    Функция имеет вид:

    MMRESULT timeSetEvent(
        UINT uDelay,	       // Задержка в мс
        UINT uResolution,	       // Разрешающая способность
        LPTIMECALLBACK lpTimeProc, // Указатель на процедуру-обработчик	
        DWORD dwUser,	       // Параметр разработчика
        UINT fuEvent	       // Тип события
       );
    
    Функция имеет седеющие параметры (я их кратко комментировал в описании функции) При успешном создании таймера возвращается его идентификатор, в случае ошибки возвращается 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