Ваш город: Не указано

Пишем калькулятор на Delphi 7 (часть2)

Итак, интерфейс калькулятора у нас готов, переходим к более сложному процессу - программированию. Как вы уже догадались, калькулятор был сделан динамически (т.е. программным способом). Соответственно все события нам придется объявить в начале программы, и затем уже связать их с элементами управления калькулятора.

Для этого найдем в начале программы ключевое слово private. После него добавляем следующую процедуру:

procedure Button1Click(Sender: TObject);

Нажимаем горячие клавиши CTRL+SHIFT+C и программа Delphi нам автоматически прописывает следующие строки:

procedure TForm1.Button1Click(Sender: TObject);
begin

end;

Данная процедура будет выводить на экран калькулятора все нажатые цифры. Если вспомнить, из предыдущей статьи мы для упрощения программирования сделали массив кнопок от 0 до 9. Однако возникает вопрос: по какой именно кнопке мы нажали? Как ее отловить? Для этого пропишем следующие строки:

(Sender as TButton).Tag:=1;
for i:=0 to 9 do
if button[i].Tag=1 then
begin
button[i].Tag:=0;
break;
end;

Соответственно при нажатии на неизвестную клавишу, мы присваиваем в поле Tag единицу. Затем с помощью цикла мы проверяем, какой из объектов содержит в свойстве Tag единицу. И таким образом мы находим номер нашей кнопки. Чтобы далее не перебирать все возможные варианты (мы же итак нашли необходимый объект), мы ставим функцию Break и цикл прерывается.

Обязательно после объявления процедуры (procedure TForm1.Button1Click(Sender: TObject);) и перед началом самой процедуры (Begin), объявим новую переменную i и присвоим ей тип integer:

var i:integer;

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

pamyatstiraniya:string;

Соответственно, нам понадобится еще одна переменная, которая хранила бы операции (+,-,*,/), и третья, которая хранила бы число, пока мы записываем новое:

pamyatoperacii:string;
pamyatchisla1:string;

Тогда в процедуре (procedure TForm1.Button1Click(Sender: TObject);) пропишем следующие условия:

if pamyatstiraniya='Надо очистить экран' then
Begin
Edit.Text:='';
pamyatstiraniya:='';
end;
if Edit.Text='0' then
Edit.Text:=inttostr(i)
else
Edit.Text:=Edit.Text+inttostr(i);

Другими словами, если мы нажали на какой-то знак +,-,*,/ - у нас в переменную pamyatstiraniya появилось сообщение, что надо очистить экран перед тем, как записать новую цифру. Дальше если у нас на экране отображался 0 - нужно эту цифру заменить на новую. И если на экране уже были цифры - их просто дописываем справа.

Процедура полностью готова к работе, но если запустить калькулятор - цифры не отображаются. Почему? Дело в том, что мы еще не связали наши кнопки 0-9 с данной процедурой. Поэтому при создании формы (procedure TForm1.FormCreate(Sender: TObject);) допишем следующие строчки:

for i:=0 to 9 do
button[i].OnClick:=Button1Click;

Запускаем калькулятор и наслаждаемся вводом цифр!

Всё было бы отлично, если бы не бесконечный ввод чисел. Поэтому давайте таким же образом сделаем операции сложения, вычитания, умножения и деления. В private пишем:

procedure Operaciya(Sender: TObject);

Нажимаем CTRL+SHIFT+C и в ней пишем следующее:

var i:integer;
begin
if sender.ClassType=TButton then
(Sender as TButton).Tag:=1;
for i:=13 to 19 do
if button[i].Tag=1 then
begin
button[i].Tag:=0;
break;
end;
case i of
13:pamyatoperacii:='+';
15:pamyatoperacii:='-';
17:pamyatoperacii:='*';
19:pamyatoperacii:='/';
end;
pamyatstiraniya:='Надо очистить экран';
end;

Здесь самое главное занести в переменную pamyatoperacii необходимый знак нашей операции (что мы будем дальше делать с выражением). Однако при выполнении операции несколько раз было бы хорошо показать пользователю результаты вычислений.

Добавим новую процедуру:

procedure Resultat(Sender: TObject);

И в ней как раз и будем производить вычисления, а затем результат - выводить на экран:

if pamyatoperacii='+' then
Edit.Text:=FloatToStr(StrToFloat(pamyatchisla1)+StrToFloat(Edit.Text));
if pamyatoperacii='-' then
Edit.Text:=FloatToStr(StrToFloat(pamyatchisla1)-StrToFloat(Edit.Text));
if pamyatoperacii='*' then
Edit.Text:=FloatToStr(StrToFloat(pamyatchisla1)*StrToFloat(Edit.Text));
if pamyatoperacii='/' then
Edit.Text:=FloatToStr(StrToFloat(pamyatchisla1)/StrToFloat(Edit.Text));
pamyatoperacii:='';
pamyatchisla1:=Edit.Text;

Поэтому в самом начале процедуры (procedure Operaciya(Sender: TObject);) будем выполнять все операции:

procedure TForm1.Operaciya(Sender: TObject);
var i:integer;
begin
Resultat(Sender);
if sender.ClassType=TButton then
(Sender as TButton).Tag:=1;
for i:=13 to 19 do
if button[i].Tag=1 then
...

И, соответственно, при создании формы, кнопки с индексами 13, 15, 17 и 19 должны быть связаны с процедурой operaciya (при нажатии на кнопку мы должны ее вызывать):

button[13].OnClick:=operaciya;
button[15].OnClick:=operaciya;
button[17].OnClick:=operaciya;
button[19].OnClick:=operaciya;

А за результаты вычисления у нас отвечает кнопка button[14]. Поэтому ее связываем с процедурой Resultat:

button[14].OnClick:=Resultat;

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

Всё работает? Переходим к следующему шагу.

Хорошо, конечно, было бы сбрасывать полностью все значения калькулятора и вычислить что-нибудь другое. Для этого настроим работу двух кнопок: CE и C. Первая отвечает за сброс при неверном вводе значений. Вторая - полный сброс всех вычислений, значений, операций и т.п. (возврат в первоначальное положение калькулятора).

Итак, в private добавим две новые процедуры:

procedure ButtonCClick(Sender: TObject);
procedure ButtonCEClick(Sender: TObject);

Нажимаем CTRL+SHIFT+C и в первую пишем:

Edit.Text:='0';
pamyatoperacii:='';
pamyatchisla1:='';

А во вторую:

Edit.Text:='0';

Дальше кнопку button[11] связываем с процедурой ButtonCEClick, а button[12] связываем с ButtonCClick:

button[11].OnClick:=ButtonCEClick;
button[12].OnClick:=ButtonCClick;

Теперь можно запрограммировать и остальные кнопки.

Backspace:

procedure TForm1.Backspace(Sender: TObject);
begin
if Length(Edit.Text)>0 then
Edit.Text:=copy(Edit.Text,1,Length(Edit.Text)-1);
if Length(Edit.Text)=0 then
Edit.Text:='0';
end;

SQRT:

procedure TForm1.Koren(Sender: TObject);
begin
Edit.Text:=FloatToStr(SQRT(StrToFloat(Edit.Text)));
end;

1/x:

procedure TForm1.Drob1nax(Sender: TObject);
begin
Edit.Text:=FloatToStr(1/(StrToFloat(Edit.Text)));
end;

, (запятая или десятичная дробь):

procedure TForm1.Drob(Sender: TObject);
var i:integer;
b:boolean;
begin
b:=false;
if pamyatstiraniya='Надо очистить экран' then
Begin
Edit.Text:='';
pamyatstiraniya:='';
end;
For i:=1 to Length(Edit.Text) do
Begin
if Edit.Text[i]=',' then
b:=true
end;
if Edit.Text[Length(Edit.Text)]=',' then
Edit.Text:=copy(Edit.Text,1,Length(Edit.Text)-1)
else
Begin
if b=false then
Edit.Text:=Edit.Text+',';
end;
end;

+/-:

procedure TForm1.Otricanie(Sender: TObject);
begin
Edit.Text:=FloatToStr(StrToFloat(Edit.Text)*(-1));
end;

Для вычисления процента нам понадобится вторая переменная pamyatchisla2 (string), которую описываем тоже вначале программы. Соответственно в процедуре ButtonCClick сбрасываем ее значение:

pamyatchisla2:='';

%:

procedure TForm1.Procent(Sender: TObject);
begin
if pamyatchisla2='' then
pamyatchisla2:=Edit.Text;
if pamyatstiraniya='Надо очистить экран' then
Edit.Text:=FloatToStr(StrToFloat(Edit.Text)/100*StrToFloat(pamyatchisla2));
end;

Проверяем, все ли у нас кнопки работают и дорабатываем программу.

Если попробовать ввести цифры с клавиатуры, то можно заметить, что у нас либо 0 постоянно мешает, либо вообще ничего не вводится. Во многом это зависит от того, где фокус находится (на кнопке или на поле ввода). Если мы нажмем мышкой на поле ввода - цифры с клавиатуры можно продолжать вводить, но вот только где они будут вводиться? Немного не в том порядке, в каком хотелось бы. Да и еще, что интереснее - можно вводить не только цифры, но и буквы - что недопустимо в калькуляторе!

Поэтому сделаем обработчик событий при вводе в поле ввода данных.

Для формы (Form1) создадим событие OnKeyPress и пропишем следующий код:

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
'0'..'9':
begin
Button[strtoint(key)].Click;
Key :=Chr(0);
Edit.SelStart:=Edit.Perform(EM_LINEINDEX,0,0)+length(Edit.Text);
Application.ProcessMessages;
Edit.SetFocus;
end;
'+':
begin
button[13].Click;
Key :=Chr(0);
end;
'-':
begin
button[15].Click;
Key :=Chr(0);
end;
'*':
begin
button[17].Click;
Key :=Chr(0);
end;
'/':
begin
button[19].Click;
Key :=Chr(0);
end;
#8 :
begin
Backspace(Sender);
Key :=Chr(0);
Edit.SelStart:=Edit.Perform(EM_LINEINDEX,0,0)+length(Edit.Text);
Application.ProcessMessages;
Edit.SetFocus;
end;
#13 :
begin
Resultat(Sender);
Key :=Chr(0);
end;
else
Key :=Chr(0);
end;
end;

Теперь свяжем наш Edit (который создается во время создания формы) с данным событием:

Edit.OnKeyPress:=FormKeyPress;

А в цикле for i:=0 to 22 do, где создаются все кнопки, свяжем их тоже с событием:

for i:=0 to 22 do
begin
...
button[i].OnKeyPress:=FormKeyPress;
end;

А при нажатии мышкой на объект - курсор перемещаем в конец строки:

procedure TForm1.EditMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
Edit.SelStart:=Edit.Perform(EM_LINEINDEX,0,0)+length(Edit.Text);
Application.ProcessMessages;
Edit.SetFocus;
end;

И, конечно же, запретим что-либо менять в нашем окошке:

Edit.ReadOnly:=true;

Клавиши вроде все работают, с окном проблем не обнаружено. Теперь обработаем пункт меню Файл>Выход:

Application.Terminate;

И Справка>О программе:

Application.MessageBox('Над программой работал: Горячкин Иван. 2013 г.','Калькулятор');

По-желанию можно добавить объект XPManifest1 с вкладки Win32. Тогда все клавиши калькулятора станут полукруглыми.

Калькулятор завершен! Теперь полностью наслаждаемся его работой (при необходимости, можно что-то изменить, добавить, доработать и т.п.).

Калькулятор на Delphi

  Вот полный код калькулятора:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,StdCtrls, Menus, ComCtrls, XPMan;

type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
StatusBar1: TStatusBar;
XPManifest1: TXPManifest;
procedure FormCreate(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure N4Click(Sender: TObject);
procedure N3Click(Sender: TObject);
private
procedure Button1Click(Sender: TObject);
procedure Operaciya(Sender: TObject);
procedure Backspace(Sender: TObject);
procedure Otricanie(Sender: TObject);
procedure ButtonCClick(Sender: TObject);
procedure ButtonCEClick(Sender: TObject);
procedure Koren(Sender: TObject);
procedure Drob(Sender: TObject);
procedure Drob1nax(Sender: TObject);
procedure Procent(Sender: TObject);
procedure Resultat(Sender: TObject);
procedure EditMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
Edit: TMemo;
Button: array[0..22] of TButton;
pamyatstiraniya:string;
pamyatoperacii:string;
pamyatchisla1:string;
pamyatchisla2:string;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
(Sender as TButton).Tag:=1;
for i:=0 to 9 do
if button[i].Tag=1 then
begin
button[i].Tag:=0;
break;
end;
if pamyatstiraniya='Надо очистить экран' then
Begin
Edit.Text:='';
pamyatstiraniya:='';
end;
if Edit.Text='0' then
Edit.Text:=inttostr(i)
else
Edit.Text:=Edit.Text+inttostr(i);
end;

procedure TForm1.Operaciya(Sender: TObject);
var i:integer;
begin
Resultat(Sender);
if sender.ClassType=TButton then
(Sender as TButton).Tag:=1;
for i:=13 to 19 do
if button[i].Tag=1 then
begin
button[i].Tag:=0;
break;
end;
case i of
13:pamyatoperacii:='+';
15:pamyatoperacii:='-';
17:pamyatoperacii:='*';
19:pamyatoperacii:='/';
end;
pamyatstiraniya:='Надо очистить экран';
end;

procedure TForm1.FormCreate(Sender: TObject);
var i,left,width,top:integer;
begin
left:=10;
width:=40;
Edit:=TMemo.Create(form1);
Edit.Parent:=form1;
Edit.Text:='0';
Edit.Width:=244;
Edit.Height:=21;
Edit.Left:=left;
Edit.Top:=20;
Edit.Alignment:=taRightJustify;
Edit.OnKeyPress:=FormKeyPress;
Edit.OnMouseDown:=EditMouseDown;
Edit.ReadOnly:=true;
Edit.SelStart:=Edit.Perform(EM_LINEINDEX,0,0)+length(Edit.Text);
for i:=0 to 22 do
begin
Button[i]:=TButton.Create(form1);
Button[i].Parent:=form1;
case i of
10..12:
begin
if i=10 then
left:=10;
Button[i].Left:=left;
Button[i].Top:=51;
Button[i].Width:=75;
left:=left+83;
end;
1..9:
begin
if i=1 then
begin
left:=10;
top:=176;
end;
left:=left+width+10;
if i mod 3 =1 then
begin
left:=10;
top:=top-30;
end;
Button[i].Width:=width;
Button[i].Left:=left;
Button[i].Top:=top;
Button[i].Caption:=inttostr(i);
end;
13..20:
begin
if i=13 then
begin
left:=button[9].Left+button[9].Width+10;
top:=206;
width:=40;
end;
left:=left+width+10;
if i mod 2 =1 then
begin
left:=button[9].Left+button[9].Width+10;
top:=top-30;
end;
Button[i].Width:=width;
Button[i].Left:=left;
Button[i].Top:=top;
end;
0:
begin
Button[0].Width:=width;
Button[0].Left:=10;
Button[0].Top:=176;
Button[i].Caption:=inttostr(i);
end;
21,22:
begin
left:=left+width+10;
if i mod 2 =1 then
left:=button[0].Left+button[9].Width+10;
Button[i].Width:=width;
Button[i].Left:=left;
Button[i].Top:=button[13].Top;
end;
end;
button[i].OnKeyPress:=FormKeyPress;
end;
button[10].Caption:='Backspace';
button[11].Caption:='CE';
button[12].Caption:='C';
button[13].Caption:='+';
button[14].Caption:='=';
button[15].Caption:='-';
button[16].Caption:='1/x';
button[17].Caption:='*';
button[18].Caption:='%';
button[19].Caption:='/';
button[20].Caption:='sqrt';
button[21].Caption:='+/-';
button[22].Caption:=',';
for i:=0 to 9 do
button[i].OnClick:=Button1Click;
button[13].OnClick:=operaciya;
button[15].OnClick:=operaciya;
button[17].OnClick:=operaciya;
button[19].OnClick:=operaciya;
button[10].OnClick:=Backspace;
button[11].OnClick:=ButtonCEClick;
button[12].OnClick:=ButtonCClick;
button[16].OnClick:=Drob1nax;
button[18].OnClick:=Procent;
button[20].OnClick:=Koren;
button[21].OnClick:=Otricanie;
button[22].OnClick:=Drob;
button[14].OnClick:=Resultat;
end;

procedure TForm1.Backspace(Sender: TObject);
begin
if Length(Edit.Text)>0 then
Edit.Text:=copy(Edit.Text,1,Length(Edit.Text)-1);
if Length(Edit.Text)=0 then
Edit.Text:='0';
end;

procedure TForm1.Otricanie(Sender: TObject);
begin
Edit.Text:=FloatToStr(StrToFloat(Edit.Text)*(-1));
end;

procedure TForm1.ButtonCEClick(Sender: TObject);
begin
Edit.Text:='0';
end;

procedure TForm1.ButtonCClick(Sender: TObject);
begin
Edit.Text:='0';
pamyatoperacii:='';
pamyatchisla1:='';
pamyatchisla2:='';
end;

procedure TForm1.Koren(Sender: TObject);
begin
Edit.Text:=FloatToStr(SQRT(StrToFloat(Edit.Text)));
end;

procedure TForm1.Drob(Sender: TObject);
var i:integer;
b:boolean;
begin
b:=false;
if pamyatstiraniya='Надо очистить экран' then
Begin
Edit.Text:='';
pamyatstiraniya:='';
end;
For i:=1 to Length(Edit.Text) do
Begin
if Edit.Text[i]=',' then
b:=true
end;
if Edit.Text[Length(Edit.Text)]=',' then
Edit.Text:=copy(Edit.Text,1,Length(Edit.Text)-1)
else
Begin
if b=false then
Edit.Text:=Edit.Text+',';
end;
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
'0'..'9':
begin
Button[strtoint(key)].Click;
Key :=Chr(0);
Edit.SelStart:=Edit.Perform(EM_LINEINDEX,0,0)+length(Edit.Text);
Application.ProcessMessages;
Edit.SetFocus;
end;
'+':
begin
button[13].Click;
Key :=Chr(0);
end;
'-':
begin
button[15].Click;
Key :=Chr(0);
end;
'*':
begin
button[17].Click;
Key :=Chr(0);
end;
'/':
begin
button[19].Click;
Key :=Chr(0);
end;
#8 :
begin
Backspace(Sender);
Key :=Chr(0);
Edit.SelStart:=Edit.Perform(EM_LINEINDEX,0,0)+length(Edit.Text);
Application.ProcessMessages;
Edit.SetFocus;
end;
#13 :
begin
Resultat(Sender);
Key :=Chr(0);
end;
else
Key :=Chr(0);
end;
end;

procedure TForm1.Drob1nax(Sender: TObject);
begin
Edit.Text:=FloatToStr(1/(StrToFloat(Edit.Text)));
end;

procedure TForm1.Procent(Sender: TObject);
begin
if pamyatchisla2='' then
pamyatchisla2:=Edit.Text;
if pamyatstiraniya='Надо очистить экран' then
Edit.Text:=FloatToStr(StrToFloat(Edit.Text)/100*StrToFloat(pamyatchisla2));
end;

procedure TForm1.Resultat(Sender: TObject);
begin
if pamyatoperacii='+' then
Edit.Text:=FloatToStr(StrToFloat(pamyatchisla1)+StrToFloat(Edit.Text));
if pamyatoperacii='-' then
Edit.Text:=FloatToStr(StrToFloat(pamyatchisla1)-StrToFloat(Edit.Text));
if pamyatoperacii='*' then
Edit.Text:=FloatToStr(StrToFloat(pamyatchisla1)*StrToFloat(Edit.Text));
if pamyatoperacii='/' then
Edit.Text:=FloatToStr(StrToFloat(pamyatchisla1)/StrToFloat(Edit.Text));
pamyatoperacii:='';
pamyatchisla1:=Edit.Text;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Application.Terminate; // чтобы освободить все процессы из памяти программы при ее завершении
end;

procedure TForm1.N4Click(Sender: TObject);
begin
Close;
end;

procedure TForm1.N3Click(Sender: TObject);
begin
Application.MessageBox('Над программой работал: Горячкин Иван. 2013 г.','Калькулятор');
end;

procedure TForm1.EditMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Edit.SelStart:=Edit.Perform(EM_LINEINDEX,0,0)+length(Edit.Text);
Application.ProcessMessages;
Edit.SetFocus;
end;

end.

 

У кого получилось разработать калькулятор - пишите в комментариях!

 

Скачать исходник калькулятора

 


<<Предыдущая статья                                     Следующая статья >>

Опубликовано: 2018-01-02 18:28:51