Итак, интерфейс калькулятора у нас готов, переходим к более сложному процессу - программированию. Как вы уже догадались, калькулятор был сделан динамически (т.е. программным способом). Соответственно все события нам придется объявить в начале программы, и затем уже связать их с элементами управления калькулятора.
Для этого найдем в начале программы ключевое слово 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. Тогда все клавиши калькулятора станут полукруглыми.
Калькулятор завершен! Теперь полностью наслаждаемся его работой (при необходимости, можно что-то изменить, добавить, доработать и т.п.).
Вот полный код калькулятора:
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.
У кого получилось разработать калькулятор - пишите в комментариях!
Скачать исходник калькулятора
<<Предыдущая статья Следующая статья >>
Опубликовано: 2013-03-24 02:30:52