Учебное пособие для студентов Авторы А. Н. Вальвачев, К. А. Сурков, Д. А. Сурков, Ю. М. Четырько Содержание Содержание 1
![]()
|
Label? А тем, что может получать фокус ввода. Кроме того, текст в поле ввода можно выделить и поместить в Буфер Обмена. Компонент Edit легко приспособить для ввода паролей. Для этого достаточно установить в свойстве PasswordChar вместо символа #0 какой-нибудь другой символ, обычно символ звездочки (*). Символ, заданный в свойстве PasswordChar отображается вместо реально вводимых символов, что мешает подсмотреть пароль посторонним. Шаг 15. В форме SettingsForm компонент Edit применяется для ввода текстового сообщения будильника. Выберите его в окне свойств и в значении свойства Text впишите "Reminder !" (рисунок 9.33). Этот текст будет появляться в редакторе при появлении окна диалога. ![]() Рисунок 9.33. Компонент Edit используется для ввода текстового сообщения будильника Шаг 16. Изменение текста во время работы программы приводит к возникновению в компоненте Edit события OnChange. Обрабатывая это событие, можно, например, устроить работу окна диалога таким образом, что кнопка OK будет недоступна, если в редакторе нет текста. Чтобы реализовать такое поведение нашего диалога, определите для компонента MessageEdit следующий обработчик события OnChange: procedure TAlarmDetailsForm.MessageEditChange(Sender: TObject); begin OkButton.Enabled := Length(MessageEdit.Text) <> 0; end; Выполните компиляцию программы и проверьте ее работу. Прежде чем продолжить обсуждение примера Alarms, сделаем несколько замечаний по поводу редактирования многострочного текста. Редактор многострочного текста представлен компонентом Memo (рисунок 9.34). ![]() Рисунок 9.34. Компонент Memo Характерные свойства компонента Memo описаны в таблице 9.10.
Таблица 9.10. Важнейшие свойства и события компонента Memo Компонент Memo похож на Edit, но в отличие от него хранит не одну строку текста, а множество строк. Доступ к строкам обеспечивает свойство Lines, представляющее собой объект класса TStrings (см. главу 3). С помощью свойства Lines строки можно добавлять, вставлять, удалять и т.д. Свойство Lines доступно в окне свойств, поэтому на стадии проектирования вы можете заполнить компонент Memo некоторым исходным текстом (рисунок 9.35). Этот текст увидит пользователь при появлении формы на экране. Ввод исходного текста осуществляется в специальном редакторе текста (String list editor), которое вызывается нажатием кнопки с многоточием в поле значения свойства Lines. ![]() Рисунок 9.35. Окно для ввода многострочного текста, отображаемого компонентом Memo Компонент Memo часто имеет одну или две полосы прокрутки (вертикальную и горизонтальную). Их появление зависит от значения свойства ScrollBars. В нашем приложении Alarms компонент Memo не нужен, но вам он безусловно пригодится в других программах. 9.3.7. Редактор с шаблоном Поскольку компонент Edit не проверяет, что вводит пользователь, он не удобен для ввода данных строго определенного формата, например телефонных номеров, времени и др. На этот случай разработчики среды Delphi предусмотрительно создали компонент MaskEdit. Он находится в палитре компонентов на вкладке Additional (рисунок 9.36). ![]() Рисунок 9.36. Компонент MaskEdit Компонент MaskEdit представляет собой поле ввода, которое вынуждает пользователя вводить данные в строго заданном формате. Во многом аналогичный компоненту Edit, он отличается от последнего тем, что имеет свойство EditMask и не имеет свойств HideSelection и OEMConvert. Свойство EditMask задает шаблон (маску) для ввода символов текста. Шаблон имеет вид текстовой строки, его символы называются форматными и управляют тем, что вводит пользователь: буквы или цифры, в каком порядке, сколько и т.д. Мы не будем утомлять вас подробным описанием форматных символов, при необходимости обратитесь к справочному руководству. Нас интересует только шаблон для ввода времени с точностью до минуты. Шаг 17. Выберите компонент TimeMaskEdit, затем в окне свойств перейдите к свойству EditMask и щелчком кнопки с многоточием откройте специальный редактор для этого свойства — Input Mask Editor (рисунок 9.37): ![]() Рисунок 9.37. Выбор шаблона для компонента MaskEdit В этом окне вы можете ввести шаблон и проверить его работу. Часто используемые шаблоны, например шаблоны телефонных номеров, даты, времени и некоторые другие, можно просто выбрать среди уже имеющихся образцов. Этой возможностью мы и воспользуемся. Выберите в списке Sample Masks пункт Short Time и щелкните на кнопке OK. Шаблон для ввода времени задан и имеет вид !90:00;1;_ . Обратите внимание, как при этом изменился компонент TimeMaskEdit (рисунок 9.38): ![]() Рисунок 9.38. Компонент MaskEdit настроен для ввода времени Шаг 18. Теперь давайте сделаем так, чтобы при появлении окна диалога поле ввода TimeMaskEdit не было пустым, а содержало текущее время. Для этого создайте у формы обработчик события OnCreate: procedure TAlarmDetailsForm.FormCreate(Sender: TObject); begin TimeMaskEdit.Text := FormatDateTime('hh:mm', Time); end; Готово. Запустите программу и убедитесь, что она работает, как вы того ожидаете. 9.3.8. Раскрывающийся список Раскрывающийся список (combo box) позволяет пользователю выбрать значение из большого множества альтернатив. Он представляет собой поле ввода, к которому прикреплен раскрывающийся список значений. Редактор служит для ввода нового значения, а список — для выбора существующего значения. Количество элементов в списке может быть произвольным, причем элементы можно динамически добавлять, удалять, заменять и т.д. Элементами списка обычно служат текстовые строки, но могут быть и графические рисунки (в последнем случае их редактирование невозможно). Раскрывающийся список представлен компонентом ComboBox, который находится в палитре компонентов на вкладке Standard (рисунок 9.39): ![]() Рисунок 9.39. Компонент ComboBox Характерные свойства компонента ComboBox собраны в таблице 9.11.
Таблица 9.11. Важнейшие свойства компонента ComboBox Раскрывающийся список умеет отображать себя по-разному в зависимости от значения свойства Style (см. таблицу 9.12).
Таблица 9.12. Значения свойства Style компонента ComboBox В двух последних случаях в компоненте ComboBox происходит событие OnDrawItem. Вы можете его перехватить и рисовать каждый элемент выпадающего списка как вам вздумается. Если элементы списка имеют разную высоту (стиль csOwnerDrawVariable), то компонент генерирует событие OnMeasureItem, чтобы узнать высоту каждого элемента. Стили csOwnerDrawFixed и csOwnerDrawVariable применяются в тех случаях, когда элементы списка должны быть рисунками. Шаг 19. Раскрывающиеся списки пригодились нам в диалоге Alarm Details для выбора дня недели (компонент WeeklyComboBox). Поскольку все дни недели заранее известны, выберите в свойстве Style значение csDropDownList (рисунок 9.40). ![]() Рисунок 9.40. Для выбора дня недели применяется компонент ComboBox в стиле csDropDownList Шаг 20. Теперь компонент WeeklyComboBox нужно заполнить списком исходных значений. Выберите его в форме, затем в окне свойств перейдите к свойству Items и нажмите кнопку с многоточием в поле значения. В появившемся окне введите список строк, как показано на рисунке 9.41. ![]() Рисунок 9.41. В этом окне вводятся элементы списка — дни недели Щелкните кнопку OK — список значений компонента WeeklyComboBox задан. Шаг 21. Выбранный элемент раскрывающегося списка определяется значением свойства ItemIndex. Начальное значение свойства равно -1, что означает — ни один элемент не выбран. Однако в компоненте WeeklyComboBox должно быть выбрано то значение, которое соответствуют текущей дате. С этой целью нужно доработать у формы обработчик события OnCreate. В итоге он будет иметь следующий вид: procedure TAlarmDetailsForm.FormCreate(Sender: TObject); begin // Установка текущего времени TimeMaskEdit.Text := FormatDateTime('hh:mm', Time); // Установка текущего дня недели WeeklyComboBox.ItemIndex := DayOfWeek(DatePicker.Date) - 1; end; Реализация метода основана на том, что компонент DatePicker при создании формы сразу содержит текущую дату. На этом с визуальной частью диалога Alarm Details покончено. Правда, мы ничего не сказали о компоненте DateTimePicker (рисунок 9.42). ![]() Рисунок 9.42. Компонент DateTimePicker Впрочем, он уже работает так, как требуется. В нем нет ничего сложного, и мы надеемся, что вы разберетесь с ним по таблице 9.13.
Таблица 9.13. Важнейшие свойства и события компонента DateTimePicker В очередной раз выполните компиляцию программы и запустите ее. Откройте окно диалога Alarm Details и хорошенько его потестируйте (рисунок 9.43). ![]() Рисунок 9.43. Тестирование окна AlarmDetails Все компоненты работают правильно. Можете поздравить себя с очередным достижением. Вы создали важную часть приложения Alarms — окно диалога, а заодно разобрались с множеством новых компонентов. 9.3.9. Установка и получение данных Окно диалога есть, но пользы от него пока нет. Все дело в том, что мы научились устанавливать параметры будильника, но не научились их принимать и хранить. Шаг 22. Для хранения параметров будильника нам нужна новая структура данных, очевидно класс объектов. Немного поразмыслив, приходим к следующему описанию: type TAlarm = class private Handled: Boolean; public MsgText: string; DateTime: TDateTime; PlaySound: Boolean; Recurring: Integer; function GetAlarmStr: string; procedure CheckTime; end; Поясним назначение полей и методов. Поле MsgText предназначено для хранения текстового сообщения. В поле DateTime записывается время и дата сигнала. Значение поля PlaySound показывает, требуется ли звуковое сопровождение сообщения. Поле Recurring определяет периодичность работы будильника и принимает следующие значения: 0 – ежедневно; 1..7 – в заданный день недели (1 — Пн, 2 — Вт, ..., 7 — Вс); 8 – однажды в заданный день. В первых двух случаях поле DateTime хранит только время, а в последнем еще и дату. Такое ухищрение позволяет организовать компактное хранение данных. Флаг Handled, объявленный в секции private, является служебным и позволит избежать повторных срабатываний, когда будильник уже прозвенел. Метод GetAlarmStr мы определили для удобства. Он будет формировать строку сообщения, содержащую время и текст напоминания. Метод CheckTime проверит, пора ли выдать сигнал и если да, то сделает это. Шаг 23. Поместите описание класса TAlarm в раздел interface модуля AlarmDetails. Затем в разделе implementation наберите текст методов GetAlarmStr и CheckTime: function TAlarm.GetAlarmStr: string; begin Result := FormatDateTime('hh:mm ', DateTime) + MsgText; end; procedure TAlarm.CheckTime; var Hour1, Min1, Sec1, MSec1: Word; Hour2, Min2, Sec2, MSec2: Word; Match: Boolean; begin // Декодировать текущее время DecodeTime(Time, Hour1, Min1, Sec1, MSec1); // Раскодировать текущее время будильника DecodeTime(DateTime, Hour2, Min2, Sec2, MSec2); // Проверить, что текущее время совпадает с временем будильника case Recurring of 0: // для ежедневной периодичности Match := (Hour1 = Hour2) and (Min1 = Min2); 1..7: // для еженедельной периодичности Match := (Hour1 = Hour2) and (Min1 = Min2) and (Recurring = DayOfWeek(Date)); 8: // для конкретной даты Match := (Hour1 = Hour2) and (Min1 = Min2) and (Int(DateTime) = Date); else Match := False; end; // Решить вопрос о выдаче сигнала будильником if Match then begin if not Handled then // сигнал! begin Handled := True; // предотвратить повторные срабатывания if PlaySound then Beep; MessageDlg(GetAlarmStr, mtWarning, [mbOk], 0); end; end else Handled := False; // обеспечить будущие срабатывания end; Для правильной работы будильника метод CheckTime должен вызываться не реже одного раза в минуту. Чем чаще вызывается метод, тем меньше инерционность будильника, но тем больше пустых опросов, а значит выше загруженность операционной системы. Компромиссная частота — два раза в секунду. Так как в одну и ту же минуту метод CheckTime будет вызван несколько раз, то для избежания повторных срабатываний используется флаг Handled. Будильник выдает сообщение только в том случае, если текущее время совпадает с временем, на которое будильник установлен и при условии, что в данную минуту он еще не звенел. Шаг 24. Давайте теперь позаботимся о передаче данных в окно диалога перед его запуском и о приеме данных после завершения. Удобнее всего, чтобы за это отвечало само окно диалога, т.е. форма AlarmDetailsForm. С этой целью определите в классе TAlarmDetilasForm два метода — GetData и SetData. Методы следует поместить в секцию public: type TAlarmDetailsForm = class(TForm) ... public procedure GetData(Alarm: TAlarm); procedure SetData(Alarm: TAlarm); end; В разделе implementation наберите программный текст методов: procedure TAlarmDetailsForm.GetData(Alarm: TAlarm); begin with Alarm do begin // Получить из диалога текст сообщения будильника MsgText := MessageEdit.Text; // Получить из диалога время срабатывания будильника DateTime := StrToTime(TimeMaskEdit.Text); // Получить из диалога состояние переключателя звука PlaySound := SoundCheckBox.Checked; // Получить из диалога периодичность срабатывания будильника if EverydayRadioButton.Checked then Recurring := 0 else if WeeklyRadioButton.Checked then Recurring := WeeklyComboBox.ItemIndex + 1 else { DateRadioButton.Checked } begin Recurring := 8; DateTime := DatePicker.Date + DateTime; end; end; end; procedure TAlarmDetailsForm.SetData(Alarm: TAlarm); begin with Alarm do begin // Установить в окне диалога текст сообщения будильника MessageEdit.Text := MsgText; // Установить в окне диалога время будильника TimeMaskEdit.Text := FormatDateTime('hh:mm', DateTime); // Установить в окне диалога состояние переключателя звука SoundCheckBox.Checked := PlaySound; // Установить в окне диалога периодичность будильника case Recurring of 0: // ежедневно EverydayRadioButton.Checked := True; 1..7: // еженедельно begin WeeklyRadioButton.Checked := True; WeeklyComboBox.ItemIndex := Recurring - 1; end; 8: // в конкретный день begin DateRadioButton.Checked := True; DatePicker.Date := Int(DateTime); end; end; end; end; Метод GetData просто заполняет поля переданного в параметре объекта Alarm значениями, которые установлены в компонентах окна диалога. Метод SetData выполняет обратные действия, заполняя компоненты окна диалога значениями, которые содержатся в полях объекта Alarm. На этом с разработкой модуля AlarmDetails покончено и окно диалога Alarm Details полностью готово к использованию. Дальше необходимо обеспечить формирование, редактирование и визуализацию списка будильников. Эта задача решается с помощью компонента ListBox. 9.3.10. Список Компонент ListBox отображает список элементов, которые пользователь может просматривать и выбирать, но не может непосредственно модифицировать. По умолчанию элементами списка являются строки, но могут быть и графические объекты. Элементы могут располагаться в одну или несколько колонок и автоматически сортироваться. При необходимости обеспечивается возможность прокрутки списка. Компонент ListBox находится в палитре компонентов на вкладке Standard (рисунок 9.44). ![]() Рисунок 9.44. Компонент ListBox Его характерные свойства собраны в таблице 9.14.
Таблица 9.14. Важнейшие свойства и события компонента ListBox Особенности хранения и отображения элементов списка определяются свойством Style, возможные значения которого описаны в таблице 9.15.
Таблица 9.15. Значения свойства Style компонента ListBox Шаг 25. Давайте воспользуемся компонентом ListBox для организации списка будильников. Активизируйте форму MainForm, а затем опустите на нее компонент ListBox. Переименуйте компонент в AlarmListBox и скорректируйте его местоположение и размеры. Затем установите свойство TabOrder в значение 0, чтобы при отображении формы список первым получил фокус ввода (рисунок 9.45). ![]() Рисунок 9.45. Компонент ListBox применяется для организации списка будильников Решим теперь вопрос хранения будильников в компоненте AlarmListBox. Для хранения элементов служит свойство Items. Свойство Items — это объект класса TStrings, в нем свойство-массив Strings хранит отображаемые строки, а свойство-массив Objects — ассоциированные со строками объекты. В нашем примере массив Strings будет хранить выдаваемые по сигналу сообщения, а массив Objects — соответствующие им объекты класса TAlarm. Теоретически все понятно, осталось реализовать все это практически. Создание, редактирование и удаление будильника осуществляется по щелчкам на кнопках NewButton, EditButton и DeleteButton соответственно. Поэтому в них требуется создать обработчики события OnClick. Шаг 26. В кнопке New... обработчик события OnClick уже существует, но его необходимо доработать: procedure TMainForm.NewButtonClick(Sender: TObject); var Alarm: TAlarm; begin AlarmDetailsForm := TAlarmDetailsForm.Create(Self); try // Выполнить диалог if AlarmDetailsForm.ShowModal = mrOK then begin // Создать новый объект будильника Alarm := TAlarm.Create; // Получить параметры будильника из диалога AlarmDetailsForm.GetData(Alarm); // Добавить будильник в список и выбрать его AlarmListBox.ItemIndex := AlarmListBox.Items.AddObject( Alarm.GetAlarmStr, Alarm); end; finally AlarmDetailsForm.Free; end; end; Метод NewButtonClick создает окно диалога Alarm Details и выполняет его в монопольном режиме. Если диалог завершается щелчком кнопки OK, создается новый объект будильника и в него переносятся данные из окна диалога. Затем этот объект добавляется в список AlarmList и его номер присваивается свойству списка ItemIndex. В результате новый элемент становится выделенным. Вы, разумеется, хотите проверить работу новоиспеченного метода. Сейчас мы так и сделаем, но прежде нужно решить небольшой вопрос. Дело в том, что при уничтожении блока списка освобождаются только строки, но не освобождаются ассоциированные с ними объекты. Хотя память объектов так или иначе освобождается при завершении приложения, мы рекомендуем всегда освобождать память явно. Это считается "хорошим тоном" программирования и иногда позволяет выявить скрытые ошибки. Освобождение использованных в форме динамических данных осуществляется в обработчике события OnDestroy. Для формы MainForm он должен быть таким: procedure TMainForm.FormDestroy(Sender: TObject); var I: Integer; begin for I := 0 to AlarmListBox.Items.Count - 1 do AlarmListBox.Items.Objects[I].Free; end; После того как вы написали этот обработчик, выполните компиляцию программы и запустите ее. Попытайтесь добавить в список несколько будильников. Если это у вас получилось, перейдем к следующему шагу — программированию реакции на нажатия кнопок Edit... и Delete. Шаг 27. Создайте в компоненте EditButton обработчик события OnClick: procedure TMainForm.EditButtonClick(Sender: TObject); var Alarm: TAlarm; SavedIndex: Integer; begin AlarmDetailsForm := TAlarmDetailsForm.Create(Self); try // Получить выбранный будильник with AlarmListBox do Alarm := TAlarm(Items.Objects[ItemIndex]); // Установить управляющие элементы диалога в соответствии с // параметрами будильника AlarmDetailsForm.SetData(Alarm); // Выполнить диалог if AlarmDetailsForm.ShowModal = mrOK then begin // Получить из диалога новые параметры будильника AlarmDetailsForm.GetData(Alarm); with AlarmListBox do begin // Запомнить номер выбранного в списке элемента SavedIndex := ItemIndex; // Изменить текст элемента // При этом элемент перестает быть выбранным Items.Strings[ItemIndex] := Alarm.GetAlarmStr; // Восстановить номер выбранного в списке элемента ItemIndex := SavedIndex; end; end; finally AlarmDetailsForm.Free; end; end; Этот метод создает окно диалога Alarm Details, инициализирует его компоненты данными из выбранного в списке объекта будильника, а затем выполняет диалог в монопольном режиме. Если диалог завершился щелчком на кнопке OK, то данные из окна диалога переносятся обратно в объект будильника и соответственно изменяется отображаемая в блоке списка строка. Так как в результате последнего действия в списке пропадает полоса выбора (свойство ItemIndex получает значение -1), номер выделенного элемента предварительно сохраняется в локальной переменной SavedIndex, а затем восстанавливается. Шаг 28. Осталось создать обработчик события OnClick в компоненте DeleteButton: procedure TMainForm.DeleteButtonClick(Sender: TObject); begin with AlarmListBox do begin // Разрушить объект будильника Items.Objects[ItemIndex].Free; // Удалить из списка соответствующую объекту строку Items.Delete(ItemIndex); end; end; Метод DeleteButtonClick удаляет объект будильника и соответствующую ему строку в списке. Обработчики событий для всех кнопок заданы, однако не спешите запускать приложение. Необходимо позаботиться о том, чтобы кнопки Edit... и Delete были доступны или недоступны в зависимости от того, выделен в списке элемент или нет. Как бы это сделать попроще? Первое решение, которое напрашивается — это вставить необходимые проверки в обработчики событий кнопок. Это неплохое решение, но оно больше подходит тем, кто привык решать задачу в лоб. Мы пойдем другим путем, воспользовавшись событием OnIdle объекта Application. В объекте Application происходит событие OnIdle в период простоя программы, например во время ожидания пользовательского ввода. Благодаря этому событию программа может выполнять некоторую фоновую работу, которая в нашем случае заключается в управлении состоянием кнопок. Для создания обработчика события 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. |