Файл: Учебное пособие для студентов Авторы А. Н. Вальвачев, К. А. Сурков, Д. А. Сурков, Ю. М. Четырько Содержание Содержание 1.doc

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.05.2024

Просмотров: 197

Скачиваний: 5

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


Для создания обработчика события OnIdle объекта Application воспользуемся уже знакомым вам компонентом ApplicationEvents (см. главу 8).

Шаг 29. Поместите в форму компонент ApplicationEvents, дайте ему одноименный идентификатор и создайте обработчик события OnIdle:

procedure TMainForm.ApplicationEventsIdle(Sender: TObject;

var Done: Boolean);

begin

EditButton.Enabled := AlarmListBox.ItemIndex <> -1;

DeleteButton.Enabled := AlarmListBox.ItemIndex <> -1;

Done := True; // предотвращает непрерывную генерацию события OnIdle

end;

В передаваемом по ссылке параметре Done метод возвращает результат своей работы. Значение True показывает, что метод нужно вызывать не постоянно в течении простоя приложения, а только по одному разу в начале каждого периода простоя.

А сейчас выполните компиляцию, запустите программу и тщательно протестируйте работу главной формы (рисунок 9.46).



Рисунок 9.46. В этом окне создается список будильников

Будильники можно создавать, добавлять, удалять. Нам осталось сделать последний шаг — заставить будильники "звонить". Для этого нужно периодически вызывать метод CheckTime у каждого помещенного в список объекта TAlarm. Периодические по времени действия выполняются с помощью таймера, о котором мы дальше и поговорим.

9.4. Законченное приложение для выдачи сигналов в заданные моменты времени

9.4.1. Таймер

Таймер — это системный генератор событий, который периодически сообщает программе о завершении заданного промежутка времени. Интервал времени между событиями таймера может устанавливаться в диапазоне от 1 до 65535 миллисекунд. Используя таймер, учитывайте, что интервалы между этими событиями оказываются неточными из-за накладных расходов механизма обработки событий Windows.

В библиотеке VCL прием событий таймера обеспечивает компонент Timer. Он расположен в палитре компонентов на вкладке System (рисунок 9.47). Им мы и воспользуемся для "оживления" будильников в приложении Alarms.



Рисунок 9.47. Компонент Timer

Шаг 30. Активизируйте форму MainForm. Затем поместите в нее компонент Timer (рисунок 9.48). Если хотите, дайте ему любое имя.



Рисунок 9.48. Компонент Timer — на форме

Шаг 31. Интервал времени между событиями таймера задается в миллисекундах как значение свойства
Interval. Изначально интервал равен 1000 миллисекунд (1 секунда). Частота контроля будильников должна быть два раза в секунду, поэтому установите свойство Interval в значение 500.

Шаг 32. Через заданные в свойстве Interval промежутки времени в компоненте Timer происходит событие OnTimer (единственное событие этого компонента). Для контроля за будильниками нам нужно создать обработчик этого события:

procedure TMainForm.TimerTimer(Sender: TObject);

var

I: Integer;

begin

for I := 0 to AlarmListBox.Items.Count - 1 do

with AlarmListBox.Items.Objects[I] as TAlarm do

CheckTime;

end;

Смысл выполняемых действий очевиден: у каждого объекта в списке будильников вызывается метод CheckTime. Таким образом, каждый будильник периодически проверяет свое время и, если нужно, выдает предупреждение (рисунок 9.49).



Рисунок 9.49. Когда будильник срабатывает, звучит сигнал и на экран выдается сообщение

Выполните компиляцию и запустите программу, чтобы проверить работу всех элементов программы. Ура! Все работает, терпение и упорство вознаграждены.

9.4.2. Файлы настроек

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

Сохранение и восстановление конфигурации осуществляется в Windows с помощью так называемых файлов настроек. Файл настроек (initialization file) — это текстовый файл, состоящий из секций. Секция начинается с имени, заключенного в квадратные скобки. В каждой секции содержатся определения некоторых связанных по смыслу параметров, представленные в виде пар Имя=Значение. Примером файла настроек может служить файл настроек проекта в системе Delphi. В нашем проекте это файл Alarms.dof.

Структуру файла настроек для программы Alarms выберем так, чтобы каждому будильнику соответствовала отдельная секция. Число секций, т.е. будильников, будем хранить в параметре AlarmCount секции Global Options. Вот как могло бы выглядеть содержимое файла:

[Global Options]

AlarmCount=3
[Alarm1]

Message=Dinner !

Time=13:00

PlaySound=1

Recurring=0
[Alarm2]

Message=Tennis training

Time=16:00

PlaySound=1

Recurring=1
[Alarm3]

Message=My favourite TV-show...

Time=22:30

PlaySound=0

Recurring=8

Date=02/25/96

Чтение и запись файла настроек осуществляется с помощью объектов TIniFile (заметьте, они не являются компонентами). Класс

TIniFile описан в модуле IniFiles. Этот модуль необходимо самостоятельно добавить в вызывающий модуль с помощью оператора uses. При создании объекта TIniFile ему в конструктор передается имя INI-файла. Позже это имя можно узнать, обратившись к свойству FileName. Если в имени файла маршрут не был указан, считается что INI-файл находится в каталоге системы Windows.

Чтение переменных из INI-файла выполняется с помощью описанных ниже методов. В этих методах название секции передается в параметре Section, имя переменной – в параметре Ident, а значение по умолчанию – в параметре Default.


ReadBool(const Section, Ident: string; Default: Boolean): Boolean — возвращает значение булевской переменной.

ReadInteger(const Section, Ident: string; Default: Longint): Longint — возвращает значение целочисленной переменной.

ReadString(const Section, Ident, Default: string): string — возвращает значение строковой переменной.

ReadSection(const Section: string; Strings: TStrings) — читает из заданной секции имена всех переменных и помещает их в объект класса TStrings.

ReadSectionValues(const Section: string; Strings: TStrings) — читает из заданной секции все пары Имя=Значение и помещает их в список. Для доступа к Значению по Имени в объектах класса TStrings существуют свойства-массивы Names и Values.

При чтении значений из INI-файла может оказаться, что заданный идентификатор или секция отсутствует. В этом случае ошибки не происходит, а функции ReadBool, ReadInteger и ReadString возвращают значение, переданное в параметре Default.

Кроме методов чтения существуют также методы записи переменных INI-файла, которые описаны ниже. В этих методах название секции передается в параметре Section, имя переменной – в параметре Ident, а значение переменной — в параметре Value.

WriteBool(const Section, Ident: string; Value: Boolean) – записывает в INI-файл булевское значение.

WriteInteger(const Section, Ident: string; Value: Longint) – записывает в INI-файл целочисленное значение.

WriteString(const Section, Ident, Value: string) – записывает в INI-файл строковое значение.

Если в момент записи значения оказывается, что заданные секция и (или) идентификатор отсутствуют, они создаются.

Удаление секций INI-файла осуществляется с помощью метода EraseSection, в который передается единственный параметр — название секции.

Шаг 33. Давайте воспользуемся описанными методами для сохранения и восстановления будильников в программе ALARMS. Работу по сохранению и восстановлению параметров одного будильника лучше всего поручить классу TAlarm. Для этого добавьте в его описание два новых метода — LoadFromIniFile и SaveToIniFile.

type

TAlarm = class

...

procedure LoadFromIniFile(IniFile: TIniFile; const Section: string);

procedure SaveToIniFile(IniFile: TIniFile; const Section: string);

end;

Метод LoadFromIniFile предназначен для чтения из INI-файла полей объекта, а метод SaveToIniFile — для записи в INI-файл полей объекта. Секция INI-файла, с которой работают эти методы, передается в параметре Section.

Шаг 34. Наберите программный код методов в разделе implementation:

procedure TAlarm.LoadFromIniFile(IniFile: TIniFile; const Section: string);

begin

with IniFile do

begin

// Прочитать текст сообщения

MsgText := ReadString(Section, 'Message', 'Reminder !');


// Прочитать строковое значение времени и

// преобразовать его в формат TdateTime

DateTime := StrToTime(ReadString(Section, 'Time', TimeToStr(Time)));

// Прочитать состояние переключателя звука

PlaySound := ReadBool(Section, 'PlaySound', True);

// Прочитать значение периодичности

Recurring := ReadInteger(Section, 'Recurring', 0);

if Recurring = 8 then

// Прочитать строковое значение даты и

// преобразовать его в формат TDateTime

DateTime := StrToDate(

ReadString(Section, 'Date', DateToStr(Date))) + DateTime;

end;

end;
procedure TAlarm.SaveToIniFile(IniFile: TIniFile; const Section: string);

begin

with IniFile do

begin

// Записать текст сообщения

WriteString(Section, 'Message', MsgText);

// Преобразовать время в строку и записать строку в INI-файл

WriteString(Section, 'Time', FormatDateTime('hh:mm', DateTime));

// Записать значение переключателя звука

WriteBool(Section, 'PlaySound', PlaySound);

// Записать значение периодичности

WriteInteger(Section, 'Recurring', Recurring);

if Recurring = 8 then

// Преобразовать дату в строку и записать строку в INI-файл

WriteString(Section, 'Date', DateToStr(DateTime));

end;

end;

Шаг 35. Перейдем теперь от сохранения и восстановления одного будильника к загрузке и восстановлению всего списка. Эти действия следует выполнять соответственно при создании и уничтожении главной формы программы, т.е. в событиях OnCreate и OnDestroy. Создайте форме MainForm обработчик события OnCreate и доработайте обработчик события OnDestroy (не забудьте подключить модуль IniFiles):

procedure TMainForm.FormCreate(Sender: TObject);

var

IniFile: TIniFile;

Alarm: TAlarm;

AlarmCount, I: Integer;

begin

IniFile := TIniFile.Create('Alarms.ini');

try

// Прочитать число будильников

AlarmCount := IniFile.ReadInteger('Global Options', 'AlarmCount', 0);

// Прочитать список будильников

for I := 1 to AlarmCount do

begin

// Создать будильник

Alarm := TAlarm.Create;

// Прочитать параметры будильника из соответствующей секции

Alarm.LoadFromIniFile(IniFile, 'Alarm' + IntToStr(I));

// Добавить будильник в список

AlarmListBox.Items.AddObject(Alarm.GetAlarmStr, Alarm);

end;

finally

IniFile.Free;

end;

end;
procedure TMainForm.FormDestroy(Sender: TObject);

var

IniFile: TIniFile;

I: Integer;

begin

IniFile := TIniFile.Create('Alarms.ini');

try

// Записать число будильников

IniFile.WriteInteger('Global Options', 'AlarmCount',

AlarmListBox.Items.Count);

// Записать список будильников