Калькулятор на VB - это легко!
(автор: Есин И. В., email: tofriend@list.ru)
О чём ...
Статья имеет две редакции: для начинающих осваивать язык и для тех у кого не только аббревиатура VBне вызывает вопросов, но и более-менее владеющих им.
В данной редакции от читателя требуется знание VB на достаточно хорошем уровне, что означает владение навыками визуального программирования, событийно-управляемого программирования и конечно «основных» операторов языка. Предлагается один из способов поиска решения подобных задач.
Первый шаг или интерфейс пользователя
Здесь особо ничего фантазировать не надо, а просто вспомнить, как выглядит обычный калькулятор, какие кнопки у него и каково их назначение. У меня получилось так:
Инструмент CommandButtonсодержит такие интересующие нас свойство и событие, которые дают нам полную ясность его выбора. Аналогичное можно сказать и про инструмент Label. Декоративный инструмент Lineнеобязателен.
Для понимания моего программного кода вам надо будет согласиться со следующими именами представленных объектов и их свойствами:
· Форме присвоим имя Calculator.
· Кнопки с цифрами образуют массив кнопок Knopkiиндексы, которых совпадают с их надписями.
· Кнопка точка - это объект с именем Tochka, aкнопка изменения знака числа [+/-] - Plusmin.
· Кнопки арифметических операций имеют общее имя Operacia, но проиндексированы. Причём кнопка с надписью + имеет индекс 4, кнопка со знаком минус - индекс 2, кнопка "разделить" - 0, а кнопка соответствующая умножению - 5.
· Кнопка "сброс"[С] - Sbros.
· Кнопка "очистить"[CE] - Ochistka.
· Кнопка "удалить"[<-] Udalit.
· Кнопка "равно" [=] -Ravno.
· Единственная метка называется Tablo (и далее - индикатор отображения вычислений будем называть "табло").
В соответствие с рисунком измените свойство Captionвсех объектов. Так, например, для объекта Tabloего значением будет 0.и свойство Font: FontSize = 14. Для всех кнопок свойство Styleимеет значение 1-Graphical. Свойство TabStopвсех объектов – False.
Свойство формы KeyPreviewобязано иметь значение True. Ведь надо же пользователю предоставить возможность вычислять с клавиатуры!
А BorderStyle -1-FixedSingle.
Немалая часть проекта уже завершена ... Продолжим работу!
Второй шаг или "как заставить эту штуковину работать?!!"
Прежде чем писать обработчики событий для данных элементов управления "возьмём в руки" обычный калькулятор и выясним "механизм" его работы. И сразу же можем сказать, что у него три состояния: включён, выключен и первоначальная готовность. Все эти состояния считайте уже написаны (они обеспечиваются открытием и закрытием окна приложения и значением свойства Captionметки Tablo)!
Далее, выясним какие действия может осуществлять пользователь над кнопками нашей вещицы и что же при этом происходит на табло?
а) Нажатие на одну из цифр - на табло справа к уже имеющемуся числу прибавляется нажатая цифра. Однако если данное число ноль, его заменяет введённая цифра.
б) Нажатие точки - изменений на табло нет.
в) Нажатие плюс/минус - на табло слева к уже имеющемуся числу прибавляется минус или убирается.
г) Выбор одной из арифметических операций - возможное вычисление значения предыдущей операции с отображением его на табло.
д) Вычислить (кнопка равно) - на табло может отобразиться результат заданной операции.
е) Удаление "последней" цифры числа - на табло удаляется "последняя" цифра.
ж) Очистить (кнопка CE) - на табло "исчезает" набранное число и "превращается" в ноль!
з) Сброс - на табло ноль.
А связаны ли как-то между собой эти действия или с какими-нибудь состояниями? И ... когда возможно данное действие, а когда нет? Ответим в той же последовательности.
а) Если была нажата точка, то набирается дробное число. Очевидно, мы не можем ввести число, которое не умещается в табло. И нам надо учитывать, что число не обязано быть целым (то есть не всегда число оканчивается точкой).
б) Нет согласованных действий. Нельзя поставить точку, если число уже дробное.
в) Нет согласованных действий. Действие можно выполнить всегда!
г) Вычисление значения заданной операции. Действие можно выполнить всегда.
д) Нет согласованных. Действие можно выполнить всегда, если значение принадлежит области допустимых значений для данной арифметической операции
е) Нет согласованных. Нельзя выполнить, если на табло ноль.
ж) Нет согласованных. Действие выполнимо всегда!
з) Состояние первоначальной готовности. Действие выполнимо всегда!
Заметим также, что включение совпадает с первоначальным состоянием нашей счётной машинки.
Итак ... определили не только какие действия может выполнить пользователь калькулятора и что при этом отобразится на табло, но и выявили некоторую взаимосвязь между действиями и даже одним состоянием. Остаётся "рассказать" про это всё компьютеру. Но каким образом? В нашем распоряжении VB!
Третий шаг или приближение к программному коду!
"Увидим" же программный код! При определении чего нам надо, будем исходить только из того какие элементы управления у пользователя "в руках", зачем ему нужен калькулятор и тех выкладок, которые мы с лёгкостью проделали в предыдущем шаге! А потребуется нам из того богатого ассортимента возможностей, который предоставляет VB всего-то несколько операторов, функций, свойств и событий известных объектов да понять какие управляющие переменные создать, каков их тип.
Как калькулятор поймет, что его только-что включили или был произведён сброс в первоначальное состояние? (з) И как он узнает какое действие ему задал пользователь? (г) Понятно, что без переменной здесь не обойтись! Поэтому в перменной mode типа String, будем хранить данные режима вычислений.
А каким образом калькулятор "запомнит" слагаемое, множитель, делимое, вычитаемое (то есть "первое" число операции)? Для этого можно объявить глобальную перменную pervoe.
На вопрос нужны ли ещё переменные отвечать пока воздержимся.
Вначале была точка.
Поскольку представление целого числа на табло оканчивается точкой, то будем "её ставить" в процедуре обработке события (далее - процедуре) Changeметки Tablo:
Private Sub Tablo_Change()
Dim z As Byte, t As Byte
z = InStr(1, Tablo.Caption, ",") ' если результат - дробное число ищем позицию запятой
t = InStr(1, Tablo.Caption, ".") ' определяем позицию точки
Ift = 0 Then
' если точка не найдётся, то ставим её в конце:
Tablo.Caption = Tablo.Caption & "."
ElseIf z <> 0 Then
' если событие наступает, в результате "выброса" на табло значения операции, которое является дробным числом, то запятую меняем на точку:
Tablo.Caption = Mid(Tablo.Caption, 1, z - 1) & "." & Mid(Tablo.Caption, z + 1, Len(Tablo.Caption) - z - 1)
EndIf
Здесь, как видите, учитывается тот случай, когда результатом операции является дробное число или уже имеется дробное число.
Учимся писать ... числа.
Теперь наступило время "набрать" нашему пользователю число! Позволим ему сделать это ... но пока с помощью мыши. При этом предусмотрим следующее: 1) он вводит цифру, когда на табло ноль.
2) он не знает (или может забыть) сколько цифр может поместиться в табло.
3) он вводит "второе" число операции, либо число после нажатия кнопки равно. 4) он вводит цифру, после того как щёлкнул по "точке".
Рассмотрение первой и второй особенности не представляет особого интереса, поскольку это нетрудно проверяется, сравнивая значение табло с "нулём" и количеством допустимых символов соответственно.
Второе число вводится после указания желаемой арифметической операции, где в соответствующей процедуре укажем значение "внутренней" переменной Tagкнопки Ravnoзначение "второе". И как только введена первая цифра "второго" числа, данная переменная становится пустым символом.
Для реализации режима ввода дробного числа воспользуемся также свойством Tag, но уже объекта Tablo, так что если его значение равно "не целое", то слева от введённой цифры будет ноль.
Данные выкладки можно реализовать в виде такого программного кода:
Private Sub knopka_Click(Index As Integer)
' если были выбраны равно или операция - ввод нового числа:
If Ravno.Tag = "второе" Then Tablo.Caption = "0": Ravno.Tag = ""
If Len(Tablo.Caption) < 16 Then
' если длина не превышает допустимой длины числа:
If Tablo.Caption = "0." And Tablo.Tag = "" Then
' если на табло ноль и нет режима начала ввода дробного числа - заменяем цифрой c точкой:
Tablo.Caption = Index & "."
Else
If Mid(Tablo.Caption, Len(Tablo.Caption), 1) = "." And Tablo.Tag <> "нецелое" Then
' на табло целое число и нет режима ввода дробного числа - добавляем цифру и ставим точку в конце:
Tablo.Caption = Mid(Tablo.Caption, 1, Len(Tablo.Caption) - 1) & Index
Else
' на табло дробное число или режим ввода дробного числа - добавляем цифру надписи табло
Tablo.Caption = Tablo.Caption & Index
End If
End If
End If
Tablo.Tag = "" ' возможен (...) вводдробногочисла
End Sub
Однако этого кода достаточно чтобы обеспечить ввод целых положительных чисел. Добавим ещё две относительно простые по пониманию процедуры. Первая - изменение знака числа:
Private Sub Plusmin_Click()
Select Case Val(Tablo.Caption)
' меньше нуля - "удаляем" минус:
Case Is < 0
Tablo.Caption = Mid(Tablo.Caption, 2, Len(Tablo.Caption))
' больше нуля - "прибавляем" минус:
Case Is > 0
Tablo.Caption = "-" & Tablo.Caption
End Select
End Sub
Другая - возможность ввода дробного числа:
Private Sub Tochka_Click()
' если число целое, то разрешаем ввести дробное число:
If Fix(Val(Tablo.Caption)) = Val(Tablo.Caption) Or Ravno.Tag = "второе" Then Tablo.Tag = "нецелое"
' к тому же ... если вводить дробное число после указания операции, то целая его часть - ноль:
If Ravno.Tag = "второе" Then Tablo.Caption = "0"