Політ: книга програмера  
0. Вступ
1. Особливості політівських програм
2. Події та їх обробники
3. Елементи керування: принципи, Button, Label, Check, Radio,
InpLine, PicCtl, Header, Progress, Track, TimerCtl, Notebook,
SpinEdit, PopupBtn, Switcher, MainMenu, Splitter, Memo, ListBox

Сайт Польоту
 

Елементи керування
Таймер - TimerCtl (модуль Ctl)

На відміну від усіх розглянутих раніше елементів керування, Таймер - не візуальний елемент. Тобто у нього немає графічного представлення, його не треба малювати в OnPaint, він ніяк не спілкується з юзером... Навіщо ж він такий потрібен? А для того, щоб викликати навішений на нього обробник чітко через задані проміжки часу. Наприклад, рівно раз на секунду.

Ну, "рівно раз на секунду" - це я дещо ідеалізую. По-перше, традиційно проміжки часу на PC вимірюються в одиницях під назвою "тік" (tick, це приблизно 1/18,2 секунди). Ось у цих тіках і задається періодичньсть спрацьовування таймера. Отже період, що точно дорівнює секунді ми задати не зможемо, бо кількість тіків має бути цілою, а в секунді 18,2 тіків. А по-друге, неважко уявити ситуацію, коли Політ буде сильно завантажений і фізично не встигатиме викликати всі таймери із замовленою частотою. Щоб зробити в цьому випадку хоч щось розумне, був придуманий параметр Times таймерного обробника. Times - це, так би мовити, за скільки разів викликається обробник. Якщо все нормально і обробник викликається своєчасно, Times=1. Якщо ж Польоту довелося пропустити виклик таймера (один чи більше разів), то при виклику обробника йому буде передано Times=2 (або більше відповідно).

Взагалі таймер використовується для організації процесів, що мають іти з певною швидкістю. Найочевидніший приклад - годинник (годинник на Панелі задач зроблений саме так). Ще таймер використовується у вікні Про Політ (для зміни кольору написів), в Арканоїді та Танках (основний цикл гри), у CD-плеєрі, Файл-менеджері, настройках клавіатури та Менеджері задач.




Створити таймер
Function TimerCtl_Create(Prog:PProg; Freq:Integer; 
  VActive:Boolean; VOnTimer:TTimerCtlProc): PControl;
  • Freq - частота виклику обробника в тіках (1/18,2 секунди).
  • VActive - флажок активності таймера. Якщо False, таймерна процедура не викликається. Активність таймера можна переключати по ходу виконання програми, див. наступну процедуру.
  • VOnTimer - процедура-обробник формату:
    TTimerCtlProc=Procedure(Me:PProg; 
      Control:PControl; Times:Integer);


Встановити активність таймера
Procedure TimerCtl_SetActive(Me:PControl; VActive:Boolean);
VActive - флажок активності (True - обробник викликається, False - ні).



Для прикладу зімітуємо годинник - такий, як на панелі задач. Для цього нам треба завести таймер (Timer), поставити йому інтервал в 18 тіків (майже 1 секунда) та написати обробник, що отримуватиме поточний час та показуватиме його у написі (Label). Щоб було цікавіше, зробимо кнопку "Зупинити годинник". Отже, робимо заготовку TestTim, додаємо в Uses модуль DOS (нам знадобиться процедура GetTime із нього). Описуємо змінні:
LabClock, BtnStop, TimTicker: PControl;
Створюємо елементи керування:
LabClock:=Ctl.Label_Create(Me, '', Nil, lsBeveled,
  alCenter);
BtnStop:=Ctl.Button_Create(Me, 'Зупинити годинник', 
  Nil, ppLeft, OnStopClick);
TimTicker:=Ctl.Timer_Create(Me, 18, True, OnTimerTick);
Малюємо:
Ctl.Label_Paint(LabClock, 10, 10, 100);
Ctl.Button_Paint(BtnStop, 10, 40, 100);
Зверніть увагу - таймер ми не малюємо.
Пишемо обробник для таймера. Він повинен просто при кожному виклику отримати час та вивести його у напис:
Procedure OnTimerTick(Me:PProg; 
  Control:PControl; Times:Integer);
Var
  H, M, S, C: Word;
  TempStr: String;
Begin
  With Me^, TTestTimData(Me^) Do
  Begin
    DOS.GetTime(H, M, S, C);
    TempStr:=D.St2(H)+':'+D.St2(M)+'.'+D.St2(S);
    Ctl.Label_SetCaption(LabClock, TempStr)
  End
End;
Кому цікаво, D.St2 - функція з модуля D, що конвертує ціле число у String довжини 2 (при необхідності додаючи нуль попереду). Тобто вигляд часу в мітці буде приблизно таким: "12:00.08".
Далі пишемо обробник натиснення кнопки BtnStop. Він повинен установити активність таймера (ввімкнути або вимкнути його) та, для краси, хай він перемикає стан натисненості кнопки. Тобто поки годинник стоятиме, кнопка "Зупинити годинник' буде натисненою.
Procedure OnStopClick(Me:PProg; Control:PControl);
Var
  StopPressed: Boolean;
Begin
  With Me^, TTestTim(Data^) Do
  Begin
    StopPressed:=Ctl.Button_GetDown(BtnStop);
    Ctl.Timer_SetActive(TimTicker, StopPressed0;
    Ctl.Button_SetDown(BtnStop, Not StopPressed)
  End
End;
Програма готова.