понедельник, 20 июня 2011 г.

Урок 14. Сохранение настроек программы


Прежде всего предлагаю выбрать на палитре компонентов Pro Delphi Lib компонент PrDAboutBox, о создании которого я рассказывал на предыдущем уроке, и установить его на форме проекта “Таймер”, изменив соответствующим образом свойства в инспекторе объектов.
О том, как это сделать и как назначить соответствующему Action команду выполнения этого компонента, смотрите в видео приложении к этому уроку.
Затем в проект добавляется форма, позволяющая задавать и сохранять настройки программы. Как это сделать, вы найдете в предыдущих уроках.
Форма заранее подготовлена. Обращаю Ваше внимание, что в этой форме используются компоненты из библиотеки EhLib, об установке которой я говорил ранее. Ниже я приведу текст программы, который содержит форма:
unit FixedBtnsSetUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OK_CANCEL, StdCtrls, Buttons, MyLabels, ExtCtrls, MyPanel, Mask,
iniFiles, DBCtrlsEh;
const CR=#13#10;
type
TForm2 = class(TForm)
MyOkButton1: TMyOkButton;
MyCancelButton1: TMyCancelButton;
MyPanel1: TMyPanel;
MyLabel1: TMyLabel;
Btn1Capt: TEdit;
Btn1Hint: TEdit;
MyLabel2: TMyLabel;
MyLabel3: TMyLabel;
MyLabel4: TMyLabel;
MyLabel5: TMyLabel;
Btn1Min: TDBNumberEditEh;
Btn1Sec: TDBNumberEditEh;
MyLabel6: TMyLabel;
Btn2Capt: TEdit;
Btn2Min: TDBNumberEditEh;
Btn2Sec: TDBNumberEditEh;
Btn2Hint: TEdit;
Btn3Capt: TEdit;
Btn3Min: TDBNumberEditEh;
Btn3Sec: TDBNumberEditEh;
Btn3Hint: TEdit;
Btn4Capt: TEdit;
Btn4Min: TDBNumberEditEh;
Btn4Sec: TDBNumberEditEh;
Btn4Hint: TEdit;
Btn5Min: TDBNumberEditEh;
Btn5Sec: TDBNumberEditEh;
Btn5Capt: TEdit;
Btn5Hint: TEdit;
MyLabel7: TMyLabel;
MyLabel8: TMyLabel;
MyLabel9: TMyLabel;
MyLabel10: TMyLabel;
Btn6Capt: TEdit;
Btn6Min: TDBNumberEditEh;
Btn6Sec: TDBNumberEditEh;
Btn6Hint: TEdit;
procedure MyCancelButton1Click(Sender: TObject);
procedure MyOkButton1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
Uses
MyTimerUnit;
procedure TForm2.FormCreate(Sender: TObject);
begin
// Присвоить имеющиеся значения
Btn1Capt.Text:=FixedBtns.B1_Caption;
Btn2Capt.Text:=FixedBtns.B2_Caption;
Btn3Capt.Text:=FixedBtns.B3_Caption;
Btn4Capt.Text:=FixedBtns.B4_Caption;
Btn5Capt.Text:=FixedBtns.B5_Caption;
Btn6Capt.Text:=FixedBtns.B6_Caption;
Btn1Min.Value:=FixedBtns.B1_Min;
Btn2Min.Value:=FixedBtns.B2_Min;
Btn3Min.Value:=FixedBtns.B3_Min;
Btn4Min.Value:=FixedBtns.B4_Min;
Btn5Min.Value:=FixedBtns.B5_Min;
Btn6Min.Value:=FixedBtns.B6_Min;
Btn1Sec.Value:=FixedBtns.B1_Sec;
Btn2Sec.Value:=FixedBtns.B2_Sec;
Btn3Sec.Value:=FixedBtns.B3_Sec;
Btn4Sec.Value:=FixedBtns.B4_Sec;
Btn5Sec.Value:=FixedBtns.B5_Sec;
Btn6Sec.Value:=FixedBtns.B6_Sec;
Btn1Hint.Text:=FixedBtns.B1_Hint;
Btn2Hint.Text:=FixedBtns.B2_Hint;
Btn3Hint.Text:=FixedBtns.B3_Hint;
Btn4Hint.Text:=FixedBtns.B4_Hint;
Btn5Hint.Text:=FixedBtns.B5_Hint;
Btn6Hint.Text:=FixedBtns.B6_Hint;
end;
procedure TForm2.MyCancelButton1Click(Sender: TObject);
begin
Form1.MyMessenger1.MessageString:='Изменения не будут сохранены'
+CR
+'Продолжить редактирование?';
Form1.MyMessenger1.TitleString:='Внимание!!!';
Form1.MyMessenger1.MessageType:=mtWarning;
Form1.MyMessenger1.Buttons:=[mbYes]+[mbNo];
If Not (Form1.MyMessenger1.ShowMessage=6)
then
close;
end;
procedure TForm2.MyOkButton1Click(Sender: TObject);
Var
ErrKod: Integer;                              // Код ошибки
ErrMes: String;                               // Описание ошибки
Label
ErrorsLab;                                      // Метка, после которой начинается текст обработчика ошибок
begin
// Стартовые значения
ErrKod:=0;
ErrMes:='Операция завершена успешно'
+CR
+'Изменения вступят в силу при следующем запуске программы';
// Первая из возможных проверок
If (Btn1Capt.Text='') //OR (Btn1Capt.Text='-')
then
begin
ErrKod:=1;
ErrMes:='Одно из полей <Подпись> осталось пустым'+CR+'Пожалуйста, заполните это поле';
GoTo ErrorsLab;
end;
If (VarIsEmpty(Btn1Min.Value)) //OR (Btn1Capt.Text='-')
then
begin
ErrKod:=1;
ErrMes:='Одно из полей <Минуты> осталось пустым'+CR+'Пожалуйста, заполните это поле';
GoTo ErrorsLab;
end;
If (VarIsEmpty(Btn1Sec.Value)) //OR (Btn1Capt.Text='-')
then
begin
ErrKod:=1;
ErrMes:='Одно из полей <Секунды> осталось пустым'+CR+'Пожалуйста, заполните это поле';
GoTo ErrorsLab;
end;
If (Btn1Hint.Text='') //OR (Btn1Capt.Text='-')
then
begin
ErrKod:=1;
ErrMes:='Одно из полей <Подсказка> осталось пустым'+CR+'Пожалуйста, заполните это поле';
GoTo ErrorsLab;
end;
// После успешного прохождения всех проверок - занесение данных в ini файл
ini:=TiniFile.Create(GetCurrentDir + '\MyTimer.ini');
Ini.WriteString('FixedBtns','B1Capt',Btn1Capt.Text);
Ini.WriteInteger('FixedBtns','B1Min',Btn1Min.Value);
Ini.WriteInteger('FixedBtns','B1Sec',Btn1Sec.Value);
Ini.WriteString('FixedBtns','B1Hnt',Btn1Hint.Text);
Ini.WriteString('FixedBtns','B2Capt',Btn2Capt.Text);
Ini.WriteInteger('FixedBtns','B2Min',Btn2Min.Value);
Ini.WriteInteger('FixedBtns','B2Sec',Btn2Sec.Value);
Ini.WriteString('FixedBtns','B2Hnt',Btn2Hint.Text);
Ini.WriteString('FixedBtns','B3Capt',Btn3Capt.Text);
Ini.WriteInteger('FixedBtns','B3Min',Btn3Min.Value);
Ini.WriteInteger('FixedBtns','B3Sec',Btn3Sec.Value);
Ini.WriteString('FixedBtns','B3Hnt',Btn3Hint.Text);
Ini.WriteString('FixedBtns','B4Capt',Btn4Capt.Text);
Ini.WriteInteger('FixedBtns','B4Min',Btn4Min.Value);
Ini.WriteInteger('FixedBtns','B4Sec',Btn4Sec.Value);
Ini.WriteString('FixedBtns','B4Hnt',Btn4Hint.Text);
Ini.WriteString('FixedBtns','B5Capt',Btn5Capt.Text);
Ini.WriteInteger('FixedBtns','B5Min',Btn5Min.Value);
Ini.WriteInteger('FixedBtns','B5Sec',Btn5Sec.Value);
Ini.WriteString('FixedBtns','B5Hnt',Btn5Hint.Text);
Ini.WriteString('FixedBtns','B6Capt',Btn6Capt.Text);
Ini.WriteInteger('FixedBtns','B6Min',Btn6Min.Value);
Ini.WriteInteger('FixedBtns','B6Sec',Btn6Sec.Value);
Ini.WriteString('FixedBtns','B6Hnt',Btn6Hint.Text);
ini.Free;
//    exit;                           // Нужен, если нет необходимости выводить сообщение об успешном завершении операции
// Вывод сообщений обработчика ошибок
ErrorsLab:
case ErrKod of            // Start Case
0:
begin
// Сообщение об успешном завершении
Form1.MyMessenger1.TitleString:='...';
Form1.MyMessenger1.MessageType:=mtInformation;
end;
else
begin
// Сообщения об ошибках
Form1.MyMessenger1.TitleString:='Ошибка ('+IntToStr(ErrKod)+')';
Form1.MyMessenger1.MessageType:=mtError;
end;
End;                   // End case
Form1.MyMessenger1.MessageString:=ErrMes;
Form1.MyMessenger1.Buttons:=[mbOk];
Form1.MyMessenger1.ShowMessage;
end;
end.
После изменения некоторых свойств формы (если Вы создавали ее заново, то это необходимо), нужно настроить вызов формы “Настройка быстрых кнопок” из основной формы приложения, для чего:
  • дайте описание модуля формы в разделе Implementation
  • перенесите оператор создания формы из кода проекта в процедуру Service_SpeedBtnsExecute
implementation
Uses
FixedBtnsSetUnit;
procedure TForm1.Service_SpeedBtnsExecute(Sender: TObject);
begin
// Настройка быстрых кнопок
Application.CreateForm(TForm2, Form2);
Form2.ShowModal;
Form2.Free;
end;
Третьим шагом в данном уроке будет добавление в главную форму проекта возможности выбора и прослушивания звукового файла. Для этого нужно расположить на форме компонент TOpenDialog (палитра Dialogs) и добавить в процедуру обработки соответствующего действия (Action) Service_SoundExecute следующий код:
procedure TForm1.Service_SoundExecute(Sender: TObject);
begin
// Выбор звукового файла для сигнала
OpenDialog1.Title:='Выбор звукового файла...';                   // Назначение заголовка окна диалога
OpenDialog1.InitialDir := ExtractFilePath(Application.ExeName);   // Задание стартовой папки
// Настройка фильтра типов файлов
OpenDialog1.Filter := 'Звуковые файлы (*.wav)|*.wav|Файлы (*.mp3)|*.mp3|Файлы (*.midi)|*.mid|Все файлы (*.*)|*.*';
OpenDialog1.FilterIndex := 1;                                    // Выбор  файлов wav - стартовый тип фильтра
if OpenDialog1.Execute                                           // Открытие окна выбора файла
then
begin
// Прослушивание
MyMessenger1.MessageString:='Хотите прослушать?';
MyMessenger1.TitleString:='?';
MyMessenger1.MessageType:=mtConfirmation;
MyMessenger1.Buttons:=[mbYes]+[mbNo];
If MyMessenger1.ShowMessage=6
then
begin
SetRecBtnStatus(2);
SetBtnStatus;
MediaPlayer1.FileName:=OpenDialog1.FileName;
MediaPlayer1.Open;
MediaPlayer1.Play;
end;
// Запись пути файла в INI
MyMessenger1.MessageString:='Установить данную мелодию как сигнал?';
MyMessenger1.TitleString:='?';
MyMessenger1.MessageType:=mtConfirmation;
MyMessenger1.Buttons:=[mbYes]+[mbNo];
If MyMessenger1.ShowMessage=6
then
begin
ini:=TiniFile.Create(ExtractFilePath(Application.ExeName) + '\MyTimer.ini');
ini.WriteString('Sound', 'SoundFullPath', OpenDialog1.FileName);
ini.Free;
end;
end;
SetRecBtnStatus(1);
SetBtnStatus;
end;
И последнее, что нужно сделать, чтобы завершить работу над проектом бытового таймера - научить собственно таймер подсчитывать интервал срабатывания на основе выбираемых или вводимых данных.
Для этого нужно создать целочисленную функцию:
Function TForm1.CalcInterval(): Integer;
begin
Result:=(Minutes.Value*60+Secunds.Value)*1000;
end;
Данная функция на основе значений полей Minutes и Secunds вычисляет интервал срабатывания таймера, переводя его в значение миллисекунд (*1000). А о том, где в программе используется данная функция, смотрите наглядный видео урок.

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

Что же дальше?
Объем выполняемого файла может оказаться достаточно велик. Существуют программные инструменты, оптимизирующие выполняемый файл. На следующем уроке с помощью одного из таких инструментов мы уменьшим объем выполняемого файла бытового таймера более, чем в два раза.

Комментариев нет:

Отправить комментарий