Файл: Учебное пособие для студентов Авторы А. Н. Вальвачев, К. А. Сурков, Д. А. Сурков, Ю. М. Четырько Содержание Содержание 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);
// Записать список будильников