Общие замечания

Приступая к решению задач этого раздела, необходимо вспомнить:

  • Процесс создания программы в Delphi состоит из двух шагов: сначала нужно создать форму программы (диалоговое окно), затем — написать процедуры обработки событий. Форма приложения (так принято называть прикладные программы, работающие в Windows) создается путем добавления в форму компонентов и последующей их настройки.
  • В форме практически любого приложения есть компоненты, которые обеспечивают интерфейс (взаимодействие) между программой и пользователем. Такие компоненты называют базовыми. К базовым компонентам можно отнести:
    • Label — поле вывода текста;
    • Edit — поле ввода/редактирования текста;
    • Button — командную кнопку;
    • CheckBox — независимую кнопку выбора;
    • RadioButton — зависимую кнопку выбора;
    • ListBox — список выбора;
    • ComboBox — комбинированный список выбора.
  • Вид компонента, его размер и поведение определяются значениями свойств (характеристик) компонента (описание свойств базовых компонентов можно найти в справочнике, во второй части книги).
  • Основную работу в программе выполняют процедуры обработки событий (описание основных событий можно найти в справочнике, во второй части книги).
  • Исходную информацию программа может получить из полей ввода/редактирования (компонент Edit), списка выбора (компонент ListBox) или комбинированного списка (компонент ComboBox). Для ввода значений логического типа можно ИСПОЛЬЗОВатЬ КОМПОНЕНТЫ CheckBox И RadioButton.
  • Результат программа может вывести в поле вывода текста (компонент Label) или в окно сообщения (функция MessageDlg).
  • Для преобразования текста, например находящегося в поле ввода/редактирования, в целое число нужно использовать функцию strToint, а в дробное — функцию strToFioat. Для преобразования целого, например значения переменной, в строку нужно использовать функцию intTostr, а для преобразования ДробНОГО — фуНКЦИЮ FloatToStr ИЛИ FloatToStrF.

1. Написать программу, которая пересчитывает скорость ветра из "метров в секунду" в "километров в час". Рекомендуемый вид формы приведен на рис. 1.1.

Рис. 1.1. Форма программы Скорость ветра

// щелчок на кнопке Пересчет
procedure TForml.ButtonlClick(Sender: TObject);
var
ms: integer; // скорость м/с
kmh: real; // скорость км/час
begin
ms := StrToInt(Edit1.Text); // ввести исходные данные
kmh := ms * 3.6; // пересчитать
// вывести результат
Label3.Caption :=
IntToStr(ms) + ' м/с — это ' +
FloatToStr(kmh) + ' км/час'
end;

2. Написать программу, которая пересчитывает скорость ветра из "метров в секунду" в "километров в час". Рекомендуемый вид формы приведен на рис. 1.1. Программа должна быть спроектирована таким образом, чтобы пользователь мог ввести в поле Скорость только целое положительное число.

// щелчок на кнопке Пересчет
procedure TForml.ButtonlClick(Sender: TObject);
var
ms: integer; // скорость м/с
kmh: real; // скорость км/час
begin
// Если поле Editl пустое, то при выполнении функции
// StrToInt возникает ошибка.
// Проверим, ввел ли пользователь скорость в поле Editl

if Length(Editl.Text) = 0 then
begin
ShowMessage('Надо ввести скорость');
exit;
// завершить обработку события
end; ms := StrToInt(Editl.Text);
// ввести исходные данные
kitih := ms * 3.6;
// пересчитать
// вывести результат
Label3.Caption :=
IntToStr(ms) + ' м/с - это ' + FloatToStr(kmh) + ' км/час1
end;
// нажатие клавиши в поле Editl
procedure TForml.EditlKeyPress(Sender: TObject; var Key:
begin
// В поле Скорость (Editl) можно ввести только
// цифры. Процедура проверяет, является ли символ
// допустимым. Если нет, то она заменяет
// введенный символ нулевым. В результате символ
// в поле редактирования не отображается.
// Key — символ, соответствующий нажатой клавише
if not ((Key >= '0') and (Key <='9') or (Key = #8))
then Key := Chr(0);
end;
Char)|

3. Написать программу, которая пересчитывает скорость ветра из "метров в секунду" в "километров в час". Рекомендуемый вид формы приведен на рис. 1.1. Программа должна быть спроектирована таким образом, чтобы пользователь мог ввести в поле Скорость только целое положительное число. Вычисление должно выполняться как в результате щелчка на кнопке Пересчет, так и при нажатии клавиши <Entei> после ввода последней цифры в поле Скорость.

// пересчитывает скорость из м/сек в км/час
procedure WindSpeed;
var
ms: integer;
// скорость м/с
kmh: real;
// скорость км/час
begin
// Если поле Editl пустое, то при выполнении
II функции StrToInt возникает ошибка.
II Проверим, ввел ли пользователь скорость в поле Editl
if Length(Forml.Editl.Text) = 0 then
begin
ShowMessage('Надо ввести скорость');
exit;
// завершить обработку события
end; ms := StrToInt(Forml.Editl.Text);
// ввести исходные данные
kmh := ms * 3.6;
// пересчитать // вывести результат
Forml.Label3.Caption :=
IntToStr(ms) + ' м/с - это ' + FloatToStr(kmh) + ' км/час'
end;
// щелчок на кнопке Пересчет
procedure TForml.ButtonlClick(Sender: TObject);
begin
WindSpeed;
// пересчитать скорость
end;
// нажатие клавиши в поле Editl
procedure TForml.EditlKeyPress(Sender: TObject; var Key: Char);
begin
// Key — символ нажатой клавиши
II #S — клавиша <Backspace>
11 #13 — клавиша <Enter> case Key of
10'..'9',#8:; // цифры и клавиша <Backspace>
#13: WindSpeed; // пересчитать скорость
else Key := Chr(O); // остальные символы не отображать
end;
end;

4. Написать программу, которая пересчитывает массу из фунтов в килограммы (1 фунт = 409,5 грамм). Рекомендуемый вид формы приведен на рис. 1.2. Программа должна быть спроектирована таким образом, чтобы кнопка Пересчет была доступна только в том случае, если пользователь ввел исходные данные.

Рис. 1.2. Форма программы Фунты-килограммы

// щелчок на кнопке Пересчет
procedure TForml.ButtonlClick(Sender: TObject);
var
funt: real; // масса в фунтах
kg: real; // масса в килограммах begin
// Кнопка Пересчет доступна только в том случае,
// если в поле Editl есть данные.
// Поэтому наличие в поле информации можно не проверять.
funt := StrToFloat(Editl.Text);
kg := funt * 0.4095;
Label2.Caption := FloatToStrFffunt,ffGeneral,5,2) + 1 ф — это
' + FloatToStrF(kg,ffGeneral,5,2) + ' кг1;
end;
// нажатие клавиши в поле Editl
procedure TForml.EditlKeyPress(Sender: TObject; var Key: Char);
begin
case Key of •
'0'.. ' 9', #8:; // цифры и клавиша <Backspace>
! Обработку десятичного разделителя
сделаем "интеллектуальной". Заменим точку и запятую на
символ DecimalSeparator — символ, который используется при записи дробных чисел.
I
I I I I .
begin
Key := DecimalSeparator;
// Проверим, введен ли уже в поле
// Edit десятичный разделитель
if pos(DecimalSeparator,Editl.Text) <> 0
then Key := Char(0); end; else Key := Char(0);
// остальные символы запрещены
end; end;
// содержимое поля Editl изменилось
procedure TForml.EditlChange(Sender: TObject);
begin
// проверим, есть ли в поле Editl исходные данные if Length(Editl.Text) = 0
then Buttonl.Enabled := False
// кнопка Пересчет недоступна else Buttonl.Enabled := True;
// кнопка Пересчет доступна end;
// Событие onCreate происходит в момент создания формы,
// до того, как форма появится на экране
procedure TForml.FormCreate(Sender: TObject); begin
{ т. к. поле Editl пустое (пользователь
еще не ввел исходные данные), то
сделаем кнопку Пересчет недоступной )
Buttonl.Enabled := False; end;

5. Написать программу, которая пересчитывает массу из фунтов в килограммы (1 фунт = 409,5 грамм). Рекомендуемый вид формы приведен на рис. 1.2. Программа должна быть спроектирована таким образом, чтобы пользователь мог ввести в поле Масса только положительное число (целое или дробное).

// щелчок на кнопке Пересчет
procedure TForml.ButtonlClick(Sender: TObject);
var
funt: real; // масса в фунтах kg: real; // масса в килограммах begin
if Length(Editl.Text) = 0 then begin
// в поле Editl нет исходной информации
ShowMessage('Надо ввести массу.1); exit; end;
funt := StrToFloat(Editl.Text); kg := funt * 0.4095;
Label2.Caption := FloatToStrF(funt, ffGeneral,5,2) +
' ф- это ' + FloatToStrF(kg,ffGeneral,5,2) + ' кг1;
end;
// нажатие клавиши в поле Edit
procedure TForml.EditIKeyPress(Sender: TObject; var Key: Char)
begin
case Key of
' 0' . . ' 9' , #8 :; // цифры и клавиша <Backspace>
I Обработку десятичного разделителя
сделаем "интеллектуальной".
Заменим точку и запятую на символ DedmalSeparator — символ,
который используется при записи дробных чисел. Этот символ задается в настройках Windows.
begin
Key := DecimalSeparator;
// проверим, введен ли уже в поле
// Edit десятичный разделитель
if pos(DecimalSeparator,Editl.Text) о О
then Key := Char (Ob-end ; else Key := Char(O); /У остальные символы запрещены
end;
end;

6. Написать программу, которая вычисляет скорость (км/час), с'которой бегун пробежал дистанцию. Рекомендуемый вид формы приведен на рис. 1.3. Количество минут задается целым числом, секунд — дробным.

Рис. 1.3. Форма программы Скорость бега

// нажатие клавиши в поле Дистанция
procedure TForml.EditlKeyPress(Sender: TObject; var Key: Char);
begin
// Key — символ, соответствующий нажатой клавише.
// Если символ недопустимый, то процедура заменяет его
// на символ с кодом 0. В результате этого символ в поле
// редактирования не появляется и у пользователя создается
// впечатление, что программа не реагирует на нажатие
// некоторых клавиш.
case Key of
1 0 ' . . ' 9 ' : ; // цифры
#8 : ; // клавиша <Backspace>
#13 : Edit2.SetFocus; // при нажатии <Enter> курсор
// переводится в поле Время-.минут
// остальные символы запрещены else Key :=Chr(0); // символ не отображать end; end;
// нажатие клавиши в поле Время-.минут
procedure TForml.Edit2KeyPress(Sender: TObject; var Key: Char);
begin
case Key of
1 0' . . ' 9 ' :
#8 : ; // клавиша <Backspace>
#13 : Edit3.SetFocus; // при нажатии <Enter> курсор
// переводится в поле Время:секунд
// остальные символы запрещены else Key :=Chr(0); // символ не отображать end; end;
// нажатие клавиши в поле Время:секунд
procedure TForml.Edit3KeyPress(Sender: TObject; var Key: Char);
begin
case Key of 1 0' . . ' 9' : ;
',','•' ! // десятичный разделитель begin
Key := DecimalSeparator;
if Pos(DecimalSeparator,Edit3.Text) о О
then Key := Char(0);
end;
#8 ' : ; // клавиша <Backspace>
#13 : Buttonl.SetFocus; // при нажатии клавиши <Enter>
// активируется кнопка Вычислить
// остальные символы — запрещены
else Key :=Chr(O); // символ не отображать
end;
end;
// щелчок на кнопке Вычислить
procedure TForml.ButtonlClick(Sender: TObject);
var
dist : integer; // дистанция, метров
rain : integer; // время, минуты
sek : real; // время, секунды v: real;
// скорость
begin
// получить исходные данные из полей ввода
dist := StrToInt(Editl.Text);
min := StrToInt(Edit2.Text);
sek := StrToFloat(Edit3.Text);
// дистанция и время не должны быть равны нулю
if (dist = 0) or ((min = 0) and (sek = 0)) then
begin
ShowMessage('Надо задать дистанцию и время.1);
exit;
end;
// вычисление
v := (dist/1000) / ((min*60 + sek)/3600);
// вывод результата
Iabel5.Caption := 'Дистанция: '+ Editl.Text + ' м' + #13 +
'Время: ' + IntToStr(min) + ' мин ' +
FloatToStrF(sek, ffGeneral,4,2) + ' сек ' +
#13 + 'Скорость: ' +
FloatToStrF(v,ffFixed,4,2) + ' км/час';
end;
if Pos(DecimalSeparator,Edit3.Text) о О
then Key := Char(0);
end;
#8 ' : ; // клавиша <Backspace>
#13 : Buttonl.SetFocus; // при нажатии клавиши <Enter>
// активируется кнопка Вычислить
// остальные символы — запрещены
else Key :=Chr(O); // символ не отображать
end;
end;
// щелчок на кнопке Вычислить
procedure TForml.ButtonlClick(Sender: TObject);
var
dist : integer; // дистанция, метров
rain : integer; // время, минуты
sek : real; // время, секунды
v: real; // скорость
begin •
// получить исходные данные из полей ввода
dist := StrToInt(Editl.Text);
min := StrToInt(Edit2.Text);
sek := StrToFloat(Edit3.Text);
// дистанция и время не должны быть равны нулю
if (dist = 0) or ((min = 0) and (sek = 0)) then
begin
ShowMessage('Надо задать дистанцию и время.1);
exit;
end;
// вычисление
v := (dist/1000) / ((min*60 + sek)/3600);
// вывод результата
Iabel5.Caption := 'Дистанция: '+ Editl.Text + ' м' + #13 +
'Время: ' + IntToStr(min) + ' мин ' +
FloatToStrF(sek, ffGeneral,4,2) + ' сек ' + #13 + 'Скорость: ' +
FloatToStrF(v,ffFixed,4,2) + ' км/час';
end;

7. Написать программу, которая вычисляет силу тока в электрической цепи. Рекомендуемый вид формы приведен на рис. 1.4. Программа должна быть спроектирована таким образом, чтобы кнопка Вычислить была доступна только в том случае, если пользователь ввел величину сопротивления.

Рис. 1.4. Форма программы Сила тока

8. Написать программу, которая вычисляет силу тока в электрической цепи. Цепь состоит из двух параллельно соединенных сопротивлений. Рекомендуемый вид формы приведен на рис. 1.5. 9. Написать программу, которая вычисляет стоимость покупки с учетом скидки. Скидка 1 % предоставляется, если сумма покупки больше 300 рублей, 2 % — если сумма больше 500 рублей, 3 % — если сумма больше 1 000. Информация о предоставленной скидке (процент и величина) должна быть выведена в диалоговом окне. Рекомендуемый вид формы программы приведен на рис. 1.6. 10. Напишите программу, которая вычисляет стоимость покупки. Пользователь должен вводить код товара и количество единиц. Программа должна формировать список товаров. Рекомен- дуемый вид формы приведен на рис. 1.7. (Развитие. Список кодов и наименований и цен товаров вводить из файла.)

<5.gif" width="316" height="281">

Рис. 1.5. Форма программы Сила тока

<6.gif" width="316" height="226">

Рис. 1.6. Форма программы Стоимость покупки

Рис. 1.7. Форма программы Супер маркет

11. Напишите программу, которая вычисляет доход по вкладу. Программа должна обеспечивать расчет простых и сложных процентов. Простые проценты начисляются в конце срока вклада, сложные — ежемесячно и прибавляются к первоначальной сумме вклада и в следующем месяце проценты начисляются на новую сумму. Рекомендуемый вид формы программы приведен на рис. 1.8.

Рис. 1.8. Форма программы Доход по вкладу

// щелчок на кнопке Вычислить
procedure TForml.ButtonlClick(Sender: TObject);
var
sum : real; // сумма вклада pr: real;
// процентная ставка srok: integer;
// срок вклада dohod: real;
// доход по вкладу
buf: real; i: integer; begin
// получить исходные данные sum := StrToFloat(Editl.Text); pr : = StrToFloat(Edit2.Text); srok := StrToInt(Edit3.Text);
if RadioButtonl.Checked then
// выбран переключатель Простые проценты dohod := sum * (pr/100) * (srok/360)
else
//т. к. в группе два переключателя, то если
// не выбран RadioButtonl, то выбран
/7 RadioButton2 — Сложные проценты begin
buf:= sum;
for i:=l to srok do
buf:= buf + buf * (pr/100);
// здесь buf — сумма в конце срока вклада
dohod := buf — sum; end;
sum := sum + dohod;
Label4.Caption := 'Доход: ' + Float-ToStrF(dohod,ffGeneral,9,2) + #13 +
1 Сумма в конце срока вклада: ' +
FloatToStrF(sum, ffGeneral,9,2),
end;
// выбор переключателя Простые проценты
procedure TForml.RadioButtonlClick(Sender: TObject);
begin
Label2.Caption := 'Срок (дней)';
Label4.Caption := ";
end;
// выбор переключателя Сложные проценты
procedure TForml.RadioButton2Click(Sender: TObject),
begin
Label2.Caption := 'Срок (мес.)';
Label4.Caption := ''; end;

12. Написать программу, которая вычисляет сопротивление электрической цепи, состоящей из двух сопротивлений. Сопротивления могут быть соединены последовательно или параллельно. Рекомендуемый вид формы приведен на рис. 1.9. Если величина сопротивления цепи превышает 1 000 Ом, то результат должен быть выведен в килоомах.

Рис. 1.9. Форма программы Сопротивление электрической цепи


// щелчок на кнопке Вычислить
procedure TForml.ButtonlClick(Sender: TObject);
var
rl,r2: real; // величины сопротивлении
r: real; // сопротивление цепи begin
// получить исходные данные
rl := StrToFloat(Edit 1.Text);
r2 := StrToFloat(Edit2.Text);
if (rl = 0) and (r2 = 0) then begin
ShowMessage('Надо задать величину хотя бы одного
сопротивления'); exit; end;
// переключатели RadioButtonl и RadioButton2
// зависимые, поэтому о типе соединения можно
// судить по состоянию одного из этих
// переключателей
if RadioButtonl.Checked
then // выбран переключатель Последовательно
r:= rl+r2
else // выбран переключатель Параллельно r:= (rl*r2)/(rl+r2);

13. Написать программу, которая вычисляет силу тока в электрической цепи. Цепь состоит из двух сопротивлений. Сопротивления могут быть соединены последовательно или параллельно. Рекомендуемый вид формы приведен на рис. 1.10.

14. Написать программу, которая, используя закон Ома, вычисляет силу тока, напряжение или сопротивление электрической цепи. Рекомендуемый вид формы приведен на рис. 1.11. Во время работы программы, в результате выбора переключателя Ток, Напряжение или Сопротивление, текст, поясняющий назначение полей ввода, должен меняться.

Рис. 1.10. Форма программы Сила тока

Рис. 1.11. Форма программы Закон Ома

// вычисление тока, напряжения или сопротивления
procedure Calculate;
var
I,U,R: real; // ток, напряжение, сопротивление begin
if Forml.RadioButtonl.Checked then
// ток
begin
U := StrToFloat(Forml.Edit1.Text) ;
R := StrToFloat(Forml.Edit2.Text); if (R <> 0) then begin
I := U/R;
Forml.Label3.Caption := 'Ток: ' + Float-ToStrF(I,ffFixed,4,2) + ' a';
end
else ShowMessage('Сопротивление не должно быть равно нулю.'), exit; end;
if Forml.RadioButton2.Checked then
// напряжение
begin
I := StrToFloat(Forml.Editl.Text);
R := StrToFloat(Forml.Edit2.Text) ; U := I*R;
Forml.Label3.Caption := 'Напряжение: ' +
FloatToStrF(U,ffFixed,4,2) exit; end;
if Forml.RadioButton3.Checked then
// сопротивление
begin
U := StrToFloat(Forml.Editl.Text); 1
:- StrToFloat(Forml.Edit2.Text); if (I <> 0) then begin
R := U/I;
Forml.Label3.Caption := 'Сопротивление:
' + Float-ToStrF(R,ffFixed,4,2) + ' Ом'; end
else ShowMessage('Ток не должен быть равен нулю.'); end;
B';
end;
.
// Выбор переключателя Ток
procedure TForml.RadioButtonlClick(Sender: TObject);
begin
Labell.Caption := 'Напряжение (вольт)';
Label2.Caption := 'Сопротивление (Ом)';
Labe13.Caption := ''; end;
// Выбор переключателя Напряжение
procedure TForml.RadioButton2Click(Sender: TObject);
begin
Labell.Caption := 'Ток (ампер)';
Label2.Caption : = 'Сопротивление (Ом)';
Label3.Caption := "; end;
// Выбор переключателя Сопротивление
procedure TForml.RadioButton3Click(Sender: TObject);
begin
Labell.Caption := 'Напряжение (вольт)1;
Label2.Caption := 'Ток (ампер)';
Label3.Caption := ''; end;
// Нажатие клавиши в поле Editl
procedure TForml.EditlKeyPress(Sender: TObject; var Key:Char);
begin
case Key of
'0'..'9',#8: ;
// цифры и клавиша <Backspase> #13: Edit2.SetFocus; // клавиша <Enter>
Г I
begin
if Key = '.'
then Key :=
// не позволяет вводить знак запятой повторно if Роз{',',Editl.Text) о О
then Key := Chr(0); end;
else Key := Chr(0); end; end;
// Нажатие клавиши в поле Edit2
procedure TForml.Edit2KeyPress(Sender: TObject; var Key:Char);
begin
case Key of
'O'..'9',#8: ;
#13: Calculate; // клавиша <Enter> — вычислить
begin
if Key = '.'
then Key := \ ' ;
// не позволяет вводить знак запятой повторно if Posf, \Edit2.Text) <> 0
then Key := Chr(0); end;
else Key := Chr(0); end; end;

// Щелчок на кнопке Вычислить
procedure TForml.ButtonlClick(Sender: TObject);
begin
if (Editl.Text <> '') and (Edit2.Text О "]
then Calculate // вычислить ток, напряжение или сопротивление
else ShowMessage('Надо ввести исходные данные в оба поля'); end;

15. Написать программу, которая вычисляет стоимость поездки на автомобиле, например, на дачу. Рекомендуемый вид формы приведен на рис. 1.12.

Рис. 1.12. Форма программы Поездка на дачу

implementation
{$R *.dfm}
I Процедура EditKeyPress обрабатывает нажатие клавиш в поле Расстояние,
Цена и Потребление. Сначала надо обычным образом создать процедуру обработки события
OnKeyPress для поля Editl, затем назначить эту процедуру событию OnKeyPres полей Edit2 и Edit3.
Кроме того, свойству Tag компонентов Editl, Edit2 и Edit3 надо присвоить
соответственно значения 1, 2 и 3. Свойство Tag используется в процедуре EditKeyPress для идентификации компонента. )
procedure TForml.EditKeyPress(Sender: TObject; var Key: Char); var
Edit: TEdit; begin
Edit := Sender as TEdit;
// в поле Edit можно ввести только дробное число
case Key of
' 0' . . ' 9' : ; // цифры
#8: ; // клавиша <Backspace>
'.',',': begin
Key := DecimalSeparator;
if Pos(DecimalSeparator,Edit.Text) о О
then Key := #0; end;
#13: // клавиша <Enter> case Edit.Tag of 1:
// клавиша нажата в поле Editl
Edit2.SetFocus; // фокус в поле Edit2 2:
// клавиша нажата в поле Editl
Edit3.SetFocus; // фокус в поле Edit3 3:
// клавиша нажата в поле Edit3
Buttonl.SetFocus; // фокус на кнопку But ton 1 end; end; end;
// щелчок на кнопке Вычислить
procedure TForml.ButtonlClick(Sender: TObject);
var
rast : real; // расстояние cena : real;
// цена
potr : real; // потребление на 100 км summ : real;
// сумма mes: string; begin
// здесь возможно исключение типа EConvertError
// в случае, если пользователь оставит // одно из полей ввода незаполненным try
rast := StrToFloat(Editl.Text);
cena := StrToFloat(Edit2.Text); potr := StrToFloat(Edit3.Text); except
on EConvertError do begin
ShowMessage('Даные надо ввести во все поля!1);
// попытаемся найти пустое поле if Length(Editl.Text) = 0
then Editl.SetFocus else if Length(Edit2.Text) = 0
else Edit3.SetFocus;
exit;
end; end; .
suinm := (rast / 100) * potr * cena; mes := 'Поездка на дачу';
if CheckBoxl.Checked then begin
summ := summ * 2; mes := mes + ' и обратно'; end;
mes := mes + 'обойдется в ' + FloatToStrF(summ,ffGeneral,4,2)
+ ' руб.';
Label4.Caption := mes; end;
end.

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

Рис. 1.13. Форма программы Калькулятор

// ****************************************************
// Вариант 1. Событие Onclick на каждой цифровой кнопке
// обрабатывает отдельная процедура.
implementation
{$R *.dfm}
var
accum: real; // аккумулятор oper: integer;
// операция: 1 — '+'; 2 — '-'; // 0 — "выполнить" (кнопка "=")
f: integer;
(' f = 0 ждем первую цифру нового числа, например,
после выполнения операции, когда на
индикаторе результат. f = 1 ждем остальные цифры. }
// кнопка О
procedure TForml.ButtonOClick(Sender: TObject);
begin
if f = 0 // первая цифра числа then begin
Editl.Text := '0'; f := 1; // ждем остальные цифры end else
if Editl.Text о '0'
// чтобы на индикаторе не было
// нескольких нулей в начале числа then Editl.Text := Editl.Text + 'О1; end;
// кнопка 1
procedure TForml.ButtonlClick(Sender: TObject);
begin
if f = 0 // первая цифра числа then begin
Editl.Text := '1'; f := 1; //' ждем остальные цифры end
32
else Edit1.Text := Edit1.Text + '1'; end;
// кнопка 2
procedure TForml .Button2Click(Sender: TObject);
begin
if (f = 0) // первая цифра числа then begin
Edit1.Text := '2'; f := 1; // ждем остальные цифры end
else Editl.Text := Edit1.Text + '2'; end;
// кнопка 3
procedure TForml.Button3Click(Sender: TObject);
begin
if f = 0 then begin
Editl.Text := '3'; f := 1; end
else Editl.Text := Editl.Text + '31; end;
// кнопка 4
procedure TForml.Button4Click(Sender: TObject);
begin
if f = 0 then begin
Editl.Text := 4'j f := 1; end
else Editl.Text := Editl.Text + '4'; end;
// кнопка 5
procedure TForml.ButtonSClick(Sender: TObject);
begin
if (f = 0)
then begin
Editl.Text := '5'; f := 1; end
else Editl.Text := Editl.Text + '5'; end;
// кнопка 6
procedure TForml.Button6Click(Sender: TObject);
begin
if f = 0 then begin
Editl.Text := '61; f := 1; end
else Editl.Text := Editl.Text + '6'; end;
// кнопка 7
procedure TForml.Button7Click(Sender: TObject);
begin
if f = 0 then begin
// первая цифра числа Editl.Text := '7' ; f := 1; end
else Editl.Text := Editl.Text + '7'; end;
// кнопка 8
procedure TForml.Button8Click(Sender: TObject);
begin
if f = 0 then begin
Editl.Text := '8'; f := 1; end
else Editl.Text := Editl.Text + ;8'; end;
// кнопка 9
procedure TForml.Button9Click(Sender: TObject);
begin
begin
Editl.Text := 'О'; accura := О; oper := 0;
f := 0; // ждем первую цифру числа end;
// нажатие клавиши в поле Editl
procedure TForml.EditlChange(Sender: TObject; var Key:Char);
begin
Key := Chr(0); // не отображать символы end;
procedure TForml.FormCreate(Sender: TObject); begin
oper := 0; end;
end.
// Вариант 2. События Onclick на всех II цифровых кнопках обрабатывает одна II процедура
implementation
{$R *.dfm}

1. Во время создания формы свойству Tag каждой цифровой кнопки надо присвоить значение,
равное цифре, которая должна появиться на индикаторе калькулятора.
2. После того как обычным образом будет создана процедура обработки события
OnClick для одной из цифровых кнопок, например для кнопки "1", надо задать,
что событие OnClick для остальных кнопок обрабатывает эта же процедура.
Делается это выбором процедуры в списке, который появляется в результате
щелчка на значке раскрывающегося списка в соответствующей строке вкладки Events.
var
accum: real;
oper: integer;

// аккумулятор
// операция: 1 — '+'; 2 — '-';
//О — "выполнить" (кнопка "=")
f: integer;
{ f = 0 ждем первую цифру нового числа, например,
после выполнения операции, когда
на индикаторе результат. f = 1 ждем остальные цифры. }
// Щелчок на кнопках "О" — "9"
procedure TForml.DigitBtnClick(Sender: TObject);
var
Btn: TButton;
ch: Char; begin
Btn := Sender as TButton;
ch := Chr(48+Btn.Tag);
// chr(48) = '0'; chr(49) = 4' и т. д.
// можно и так: ch := Btn.Caption;
case Btn.Tag of
1..9: // кнопки "1" - "9"
if f = 0 // первая цифра числа then begin
Editl.Text := ch; f := 1;
// ждем остальные цифры end else Editl.Text := Editl.Text + ch;
0: // кнопка "О"
if Editl.Text <> '0' //на индикаторе О
// чтобы на индикаторе не было
// нескольких нулей в начале числа then Editl.Text := Editl.Text + 'О1; end; end;
// десятичная точка
procedure TForml.ButtonZClick(Sender: TObject);
begin
if Editl.Text = '0' then
begin
Edit1.Text := '0, ' ; f := 1; end; if Pos (', ',Editl.Text) = 0 then
Editl.Text := Editl.Text + ','; end;
// выполнение операции procedure DoOper; var
numb: real; // число на индикаторе begin
// accum содержит результат предыдущей
// операции, орег — код операции, которую
// надо выполнить. Операнд находится // на индикаторе.
numb := StrToFloat(Forml.Editl.Text); case oper of 0:
accum := numb; 1: accum := accum + numb; 2: accum := accum — numb; end;
Forml.Editl.Text := FloatToStr(accum); end;
// Обрабатывает щелчок на кнопках "+", "-" и "="
procedure TForml.OpBtnClick(Sender: TObject);
l Надо выполнить предыдущую операцию, вывести результат
на индикатор, запомнить текущую операцию и установить
режим ожидания первой цифры нового числа. } var
Btn: TButton; begin
Btn := Sender as TButton;
if f = 0 // ждем первую цифру, но пользователь
// щелкнул на кнопке операции then
// свойство Tag кнопки хранит код операции oper := Btn.Tag
// запомним операцию else begin
DoOper; // выполнить предыдущую операцию oper := Btn.Tag; // запомнить текущую операцию f1=0; // ждем первую цифру нового числа
end; end;
// кнопка "с" — очистка
procedure TForml.ButtonCClick(Sender: TObject);
begin
Edit1.Text := '0';
accum := 0;
oper := 0;
f := 0; // ждем первую цифру числа end;
// нажатие клавиши в поле Editl
procedure TForml.EditIChange(Sender: TObject; var Key:Char);
begin
Key := Chr(0); // не отображать символы end;
procedure TForml.FormCreate(Sender: TObject); begin
oper := 0; end;
end.

17. Напишите программу "Электронные часы", на поверхности формы которой отображается текущее время (рис. 1.14).

Рис. 1.14. Окно программы Электронные часы

unit eclock_; interface
uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;
type
TForml = class(TForm)
Timerl: TTimer;
Labell: TLabel;
procedure FormPaint(Sender: TObject);
procedure TimerlTimer(Sender: TObject);
procedure FormCreate(Sender: TObject);
// объявление процедуры ShowTime
// помещено сюда вручную
// это сделано, чтобы функция имела
// доступ к компонентам формы напрямую
procedure ShowTime;
private
f Private declarations }
public
{ Public declarations }
end;var "
Forml: TForml;implementation($R *.dfm}// отображает текущее время
procedure TForml.ShowTime;
var
Time: TDateTime; // текущее время
begin
Time := Now(); // получить системное время
Label1.Caption := FormatDateTime('hh:mm:ss',Time);
end;// обработка события Paint
procedure TForml.FormPaint(Sender: TObject);
begin
ShowTime; // отобразить часы
end;// обработка сигнала таймера
procedure TForml.TimerlTimer(Sender: TObject);begin
ShowTime; // отобразить время
end;procedure TForml.FormCreate(Sender: TObject);
begin
// настроить и запустить таймер
Тimer1.Interval := 1000; // период сигналов таймера 1 с
Timerl.Enabled := True; // пуск таймера
end;end.

18. Напишите программу "Электронные часы", в окне которой отображается текущее время и дата (рис. 1.15).

Рис. 1.15. В окне программы Электронные часы отображается текущее время и дата

unit eclock_2_;interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, ExtCtrls, StdCtrls;
type
TForml = class(TForm)
Timerl: TTimer;
Label1: TLabel;
Label2: TLabel;
Shapel: TShape;
procedure FormPaint(Sender: TObject);
procedure TimerITimer(Sender: TObject);
procedure FormCreate(Sender: TObject);
42Часть 1
// Объявление процедуры ShowTime
// помещено сюда вручную.
// Это сделано, чтобы функция имела
// доступ к компонентам формы напрямую
procedure ShowTime; private
/ Private declarations }
public
{ Public declarations }
end;var
Forml: TForml;implementation{$R *.dfm}// отображает текущее время
procedure TForml.ShowTime; "
var
Time: TDateTime; // текущее время
begin
Time := Now(); // получить системное время
Labe11.Caption := FormatDateTime('hh:mm:ss',Time);
end;// обработка события Paint
procedure TForml.FormPaint(Sender: TObj ect);
begin
ShowTime; // отобразить часы
end;// обработка сигнала таймера
procedure TForml.TimerITimer(Sender: TObject);
begin
ShowTime; // отобразить время
end;procedure TForml.FormCreate(Sender: TObject);
begin
Label2.Caption := FormatDateTime('dd.mm.yyyy',Now())
Примеры и задачи_43_ // настроить и запустить таймер
Timerl.Interval := 1000; // период сигналов таймера 1 с
TimerI.Enabled := True; // пуск таймера
end;
end.

19. Напишите программу "Электронные часы", в окне которой
отображается текущее время, дата и день недели (рис. 1.16).

Рис. 1.16. В окне программы Электронные часы отображается текущее время, дата и день недели

unit eclock_3_;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, ExtCtrls, StdCtrls;
type
TForml - class(TForm)
Timerl: TTimer;
Labell: TLabel; // время
Label2: TLabel; // дата и день недели
procedure FormPaint(Sender: TObject);
procedure TimerlTimer(Sender: TObject);
procedure FormCreate(Sender: TObject);
// Объявление процедуры ShowTime
// помещено сюда вручную.
// Это сделано, чтобы функция имела
// доступ к компонентам формы напрямую
procedure ShowTime;
private
/ Private declarations }
public
{ Public declarations j
end';

var
Forml: TForml;

implementation

const
stDay : array[1..7J of stringfll) =
('воскресенье1,'понедельник1,'вторник',
'среда','четверг','пятница',¦суббота');

stMonth : array[1..12] of string[8] =
('января','февраля','марта',
'апреля1, 'мая','июня','июля',
'августа','сентября', 'октября',
'ноября','декабря'); ,

{$R *.dfm)

// отображает текущее время
procedure TForml.ShowTime;
var
Time: TDateTime; // текущее время
begin
Time :¦ Now(); // получить системное время
Labell.Caption := FormatDateTime('hh:mm:ss',Time);
end;

// обработка события Paint
procedure TForml.FormPaint(Sender: TObject);
begin
ShowTime; // отобразить часы
end;

// обработка сигнала таймера
procedure TForml.TimerlTimer(Sender: TObject);
begin
ShowTime; // отобразить время
end;

/7 обработка события OnCreate
procedure TForml.FormCreate(Sender: TObject);
var
Present: TDateTime; // текущая дата и время
Year, Month, Day : Word; // 1Х>д, месяц и число, как
// отдельные числа
begin

Present:= Now; // получить текущую дату
DecodeDate(Present, Year, Month, Day);
Label2.Caption := 'Сегодня '+IntToStr(Day)+ ' ' +
stMonth[Month] + ' '+ IntToStr(Year)+
' года, '+ stDay[DayOfWeek(Present)];

// настроить и запустить таймер
Timerl.Interval := 1000; // период сигналов таймера 1 с
Timerl.Enabled := True; // пуск таймера
end;

end.

20. Напишите программу "Таймер". На рис. 1.17 приведена
форма и окна программы во время установки интервала и в
процессе отсчета времени.



Рис. 1.17. Форма и окна программы Таймер implementation

($R *.dfm}

{ Во время создания формы свойству Visible компонента
Label3 надо присвоить значение False )
var
// интервал
rain: integer; // минут
sec: integer; // секунд

// в заголовок окна программы
// выводится, сколько времени осталось
procedure ShowTime;
var
buf: string[20];
begin
// минуты и секунды выводим двумя цифрами
if min < 10 then
buf := '0' + IntToStr(min) + ':'
else ,
buf := IntToStr(min) + ':';

if sec < 10 then
buf := buf + '0' + IntToStr(sec)
else
buf := buf + IntToStr(sec);

Forml.Label3.Caption := buf;
end;

// сигнал от таймера
procedure TForml.TimerlTimer(Sender: TObject);
begin
sec := sec — 1;
ShowTime; // показать, сколько времени осталось
if (min = 0) and (sec = 0) then
// заданный интервал истек
begin
Timerl.Enabled := False; // стоп
ShowMessage('Заданный интервал истек!');
Buttonl.Caption := 'Пуск';
Label3.Visible := False; // скрыть индикацию времени
// сделать видимыми поля ввода интервала
Labell.Visible := True;
Editl.Visible := True;
Label2.Visible := True;
Edit2.Visible := True;
exit;
end;

if (sec = 0) and (min > 0) then
begin
sec : = 60;
min := min — 1;
end;

end;

// щелчок на кнопке Пуск/Стоп
procedure TForml.Buttoniciick(Sender: TObject);
begin
if Forml.Timer1.Enabled then
// таймер работает, надо остановить
begin
Timer1.Enabled := False; // стоп
Buttonl.Caption := 'Пуск';
Label3.Visible := False; // скрыть индикацию времени
// сделать видимыми поля ввода интервала
Labell.Visible := True;
Editl.Visible := True;
Label2.Visible := True;
Edit2.Visible := True;
end

else
// таймер стоит, надо запустить
begin
min := StrToInt(Editl.Text);
sec := StrToInt(Edit2.Text);
if (sec = 0) and (min = 0) then
begin
ShowMessage('Надо задать интервал!');
exit;
end;
Timerl.Enabled
// скрыть поля ввода интервала
Label1.Visible
Editl.Visible
Label2.Visible
Edit2.Visible
Label3.Visible
= True; // запустить таймер
= False;
= False;
= False;
= False;
= True;
Buttonl.Caption := 'Стоп';
ShowTime;
end;
end;

21. Усовершенствуйте программу "Таймер" так, чтобы по исте чении установленного интервала программа привлекала внимание пользователя звуковым сигналом, например, одним из стан дартных звуков Windows.

implementation

{$R *.dfm)

const
SOUND = 'tada.wav';
var
MediaPlayer : TMediaPlayer; // обеспечивает воспроизведение
// звукового фрагмента
// интервал
min: integer; // минут
sec: integer; // секунд

// в заголовок окна программы
// выводит, сколько времени осталось
procedure ShowTime;
var
buf: string[20];
begin
// минуты и секунды выводим двумя цифрами
if min < 10 then
buf := '0' + IntToStr(min) + ':'
else
buf := IntToStr(min) + ':';
if sec < 10 then
buf := buf + '0' + intToStr(sec)
else
buf := buf + IntToStr(sec);

Forml.Label3.Caption := buf;
end;

// сигнал от таймера
procedure TForml.TimerlTimer(Sender: TObject);
begin
sec := sec — 1;
ShowTime; // показать, сколько времени осталось
if (min = 0) and (sec = 0) then
// заданный интервал истек
begin
Timer1.Enabled := False; // стоп

// *** звуковой сигнал ****
//т. к. возможно, что WAV-файл не был
// загружен (см. FormCreate),
// то может возникнуть исключение
try
MediaPlayer.Play; // воспроизвести звуковой фрагмент
except
on EMCIDeviceError do;
end;

ShowMessage('Заданный интервал истек!');
Buttonl.Caption := 'Пуск';
Label3.Visible := False; // скрыть индикацию времени
// сделать видимыми поля ввода интервала
Labell.Visible := True;
Editl.Visible := True;
Label2.Visible := True;
Edit2.Visible := True;
exit;
end;

if (sec = 0) and (min > 0) then
begin
sec := 60;

min := min — 1;
end;
end;

// щелчок на кнопке Пуск/Стоп
procedure TForml.ButtonlClick(Sender: TObject);
begin
if Forml.Timerl.Enabled then
// таймер работает, надо остановить
begin
Timerl.Enabled
Buttonl.Caption
Label3.Visible
// сделать видимыми поля ввода интервала
Labell.Visible
Editl.Visible
Label2.Visible
Edit2.Visible
= False; // стоп
:= 'Пуск';
= False; // скрыть индикацию времени
= True;
= True;
= True;
= True;
end

else .
// таймер стоит, надо запустить
begin
min := StrToInt(Editl.Text);
sec := StrToInt(Edit2.Text);
if (sec = 0) and (min = 0) then
begin
ShowMessage('Надо задать интервал!');
exit;
end;

Timerl.Enabled := True; // запустить таймер
// скрыть поля ввода интервала
Labell.Visible
Editl.Visible
Label2.Visible
Edit2.Visible
Label3.Visible
= False;
¦ False;
= False;
= False;
= True;
Buttonl.Caption := 'Стоп';
ShowTime;
end;
end;

// создает компонент MediaPlayer и
// загружает WAV-файл
procedure TForml.FormCreate(Sender: TObject);
var
pWinDir: PChar; // указатель на nul-terminated-строку
sWinDir: String[80];
begin
// создадим компонент MediaPlayer
MediaPlayer : = TMediaPlayer.Create(self);
MediaPlayer.ParentWindow := Forml.Handle;
MediaPlayer.Visible := False;

// Стандартные WAV-файлы находятся в каталоге Media,
// но где находится и как называется каталог, в который
// установлен Windows? Выясним это.
// Чтобы получить имя каталога Windows,
// воспользуемся API-функцией GetWindowsDirectory.
// Строка, которая передается в API-функцию,
// должна быть nul-terminated-строкой.

// Получить имя каталога Windows
GetMem(pWinDir,80); // выделить память
// для строки
GetWindowsDirectory(pWinDir,80); // получить каталог Windows
sWinDir := pWindir;

// открыть WAV-файл
MediaPlayer.FileName := sWinDir + '\media\' + SOUND;
try
MediaPlayer.Open;
except
on EMCIDeviceError do;
end;
end;

end.

22. Напишите программу "Таймер". Для ввода интервала используйте компоненты upDown. Рекомендуемый вид формы при веден на рис. 1.18.


Рис. 1.18. Форма программы Таймер

( Чтобы обеспечить синхронизацию компонентов UpDown и Edit, нужно в свойство Associate компонента UpDown записать имя соответствующего компонента Edit.
Это надо сделать во время создания формы. )

var
// интервал
min: integer; // минут
sec: integer; // секунд •

// в заголовок окна программа
// выводит, сколько времени осталось
procedure ShowTime;
var
buf: string[20];
begin
buf := 'Таймер ';
// минуты и секунды выводим двумя цифрами
if min < 10 then
buf := buf + '0' + IntToStr(min) + ' : '
else
buf := buf + IntToStr(min) + ' : ';

if sec < 10 then
buf := buf + '0' + IntToStr(sec)
else
buf := buf + IntToStr(sec);

Forml.Caption := buf;
end;
// сигнал от таймера
procedure TForml.TimerlTimer(Sender: TObject);
begin
sec := sec - 1;
if (min = 0) and {sec = 0) then
// заданный интервал истек
begin
Timerl.Enabled := False; // остановить таймер
UpDownl.Enabled := True;
UpDown2.Enabled := True ;
Editl.Enabled := True;
Edit2.Enabled :¦ True;
Buttonl.Caption := 'Пуск';
ShowMessage('Заданный интервал истек!');
exit;
end;

if (sec = 0) and (min > 0) then
begin
sec := 60;
min := min — 1;
end;

ShowTime; // показать, сколько времени осталось
end;

// щелчок на кнопке Пуск/Стоп
procedure TForml.ButtonlClick(Sender: TObject);
begin
if Forml.Timerl.Enabled then
// таймер работает, надо остановить
begin
Timerl.Enabled := False; // стоп
Forml.Caption := 'Таймер1;
Buttonl.Caption := 'Пуск1;
// разрешить ввод интервала
UpDownl.Enabled:= True;
UpDown2.Enabled:= True;
Editl.Enabled := True;
Edit2.Enabled := True;
end
_
else
// таймер стоит, надо запустить
begin
min := UpDownl.Position;
sec := UpDown2.Position;
if (sec = 0) and (min = 0) then
begin
ShowMessage('Надо задать интервал!');
exit;
end;

Editl.Enabled := False;
Edit2.Enabled := False;
UpDownl.Enabled:= False;
UpDown2.Enabled:= False;
Buttonl.Caption := 'Стоп1;
Timer1.Enabled := True; // пуск таймера
ShowTime;
end;
end;

end.