Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi.pdf
Скачиваний:
191
Добавлен:
24.02.2016
Размер:
6.84 Mб
Скачать

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

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

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

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

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

9.4.1. Таймер

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

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

472

Рисунок 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. Таким образом, каждый

473

будильник периодически проверяет свое время и, если нужно, выдает предупреждение (рисунок 9.49).

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

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

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

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

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

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

474

[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) — читает из заданной секции все пары Имя=Значение и помещает их в список. Для

475

доступа к Значению по Имени в объектах класса 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-файл полей объекта.

476

Секция 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. Создайте форме

477

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

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

for I := 0 to AlarmListBox.Items.Count - 1 do with AlarmListBox.Items.Objects[I] as TAlarm do

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

SaveToIniFile(IniFile, 'Alarm' + IntToStr(I + 1)); finally

IniFile.Free;

for I := 0 to AlarmListBox.Items.Count - 1 do AlarmListBox.Items.Objects[I].Free;

end;

end;

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

478

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]