Калькулятор на VB - это легко!
(автор: Есин И. В., email: tofriend@list.ru)
О чём ...
Статья имеет две редакции: для начинающих осваивать язык и для тех у кого не только аббревиатура VB не вызывает вопросов, но и более-менее владеющих им.
В данной редакции от читателя требуется знание VB на достаточно
хорошем уровне, что означает владение навыками визуального
программирования, событийно-управляемого программирования и конечно
«основных» операторов языка. Предлагается один из способов поиска решения
подобных задач.
Первый шаг или интерфейс пользователя
Здесь особо ничего фантазировать не надо, а просто вспомнить, как
выглядит обычный калькулятор, какие кнопки у него и каково их назначение.
У меня получилось так:
[pic]
Инструмент CommandButton содержит такие интересующие нас свойство и событие, которые дают нам полную ясность его выбора. Аналогичное можно сказать и про инструмент Label. Декоративный инструмент Line необязателен.
Для понимания моего программного кода вам надо будет согласиться со следующими именами представленных объектов и их свойствами:
0. Форме присвоим имя Calculator.
1. Кнопки с цифрами образуют массив кнопок Knopki индексы, которых совпадают с их надписями.
2. Кнопка точка - это объект с именем Tochka, a кнопка изменения знака числа [+/-] - Plusmin.
3. Кнопки арифметических операций имеют общее имя Operacia, но проиндексированы. Причём кнопка с надписью + имеет индекс 4, кнопка со знаком минус - индекс 2, кнопка "разделить" - 0, а кнопка соответствующая умножению - 5.
4. Кнопка "сброс" [С] - Sbros.
5. Кнопка "очистить" [CE] - Ochistka.
6. Кнопка "удалить" [ 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"
End Sub
Исправление ошибок ...
Позволим также стирать набранное число и удалять последнюю цифру числа на табло, что обеспечит следующий фрагмент программного кода:
Private Sub ochistka_Click()
' щелчёк по кнопке CE "превращает" число на табло в ноль:
Tablo.Caption = "0"
Tablo.Tag = "" ' вводим целое число
End Sub
Private Sub udalit_Click()
umnaya.SetFocus
' является ли число целым?
If Fix(Val(Tablo.Caption)) = Val(Tablo.Caption) Then
' если целое - удалим последнюю цифру
Tablo.Caption = Mid(Tablo.Caption, 1, Len(Tablo.Caption) - 2)
' а если число было нулём - то так и оставим - "ноль":
If Tablo.Caption = "." Then Tablo.Caption = "0"
Else
' если на табло число не целое, то просто удалим последнюю цифру надписи
Tablo.Caption = Mid(Tablo.Caption, 1, Len(Tablo.Caption) - 1)
End If
End Sub
Считать, считать и ещё раз считать!
Далее пользователь, скорее всего, захочет указать одно из арифметических
действий: сложить, вычесть, умножить, разделить заданное число с каким-то
другим. Предоставим ему такую возможность!
Здесь необходимо предусмотреть следующее: 1) пользователь может изменить
выбранную операцию (не изменив до этого числа на табло), 2) если
пользователь уже выбирал до этого какую-то операцию, не вычислял её
значение с помощью клавиши равно или не задавал состояние первоначальной
готовности, то вычисляется результат этой операции.
Легко понять, что эти особенности взаимосвязаны между собой: вторая
возможна только тогда, кода пользователь не изменяет выбор операции.
Первая особенность выбора арифметического действия частично рассмотрена.
Вспомним, что при указании пользователем операции программа запишет в
переменную Ravno.Tag значение "второе". Таким образом, при вхождении в
процедуру обработки события щелчка мыши по одной из кнопок Operacia
условный оператор программного кода с помощью данной переменной проверит:
"А не изменяет ли пользователь выбранную операцию?!". При отрицательном
ответе с помощью переменной deystvie будет решать надо ли передавать
управление процедуре вычисления значения резултата Rezultat(). В любых
случаях, переменная deystvie примет значение соответствующее выбранному
арифметическому действию. При этом уже знакомая нам переменная pervoe
примет значение числа табло, а Ravno.Tag будет сообщать процедуре ввода
числа, что вводится новое число и предоставлять возможность изменить
операцию. Всё это находим в следующей процедуре:
Private Sub Operacia_Click(Index As Integer)
If Ravno.Tag = "" Then ' нет изменения выбора операции?
' если операция была задана - вычисляем её значение:
If deystvie "нет" Then vtoroe = Val(Tablo.Caption): rezultat
End If
Select Case Index ' запишем выбранное действие
Case 0 deystvie = "разделить"
Case 2 deystvie = "вычесть"
Case 4 deystvie = "сложить"
Case 5 deystvie = "умножить"
End Select
pervoe = Val(Tablo.Caption) ' первое число операции - то что на табло при выборе операции
Ravno.Tag = "второе" ' режим ввода второго числа
End Sub
Несложно догадаться, что процедура вычисления результата будет вызываться
также из процедуры обработки нажатия кнопки "равно". И прежде чем
рассматривать первую, напишем программный код для второй.
Сделаем так, что если: 1) второе число не введено и кнопка "равно"
нажимается один раз, то значение не вычисляется, 2) если кнопка нажимается
два раза подряд, то в качестве второго числа операции выбирается текущее
число табло и результат вычисляется.
Во всех случаях нам будет способствовать переменная Ravno.Tag. Если она равна "второе", то это удовлетворяет первому условию. Однако чтобы реализовать второе назначим данной переменной пустой символ. И уже здесь вследствие условия положим значение переменной vtoroe число, "которое на табло" и запустим процедуру Rezultat(), затем зададим калькулятору подобие начального состояния (без отображения на табло нуля). Можно написать так:
Private Sub Ravno_Click()
If Ravno.Tag "второе" Then
vtoroe = Val(Tablo.Caption)
Call rezultat
Ravno.Tag = "второе" ' режим ввода "второго" числа
Tablo.Tag = "" ' две переменные ука- deystvie = "нет" ' зывают начальное состояние
Else
Ravno.Tag = "" ' можем в "следующий раз" считать первым числом текущее число табло
End If
End Sub
«Ноль», «нельзя» и «делить»
А вот и процедура обработки результата (понимание которой у вас, я думаю, не составит труда):
Private Sub rezultat()
Select Case deystvie
Case "сложить"
Tablo.Caption = pervoe + vtoroe
Case "вычесть"
Tablo.Caption = pervoe - vtoroe
Case "разделить"
If vtoroe 0 Then
Tablo.Caption = pervoe / vtoroe
Else ' на ноль действительно нельзя делить!
Tablo.Caption = "на ноль не делят!"
End If
Case "умножить"
Tablo.Caption = pervoe * vtoroe
End Select
End Sub
В ней, как видите, результат сразу "выбрасывается" на табло.
О пользе клавиатуры.
И прежде чем подготовиться к последнему желанию пользователя - иметь возможность производить вычисления с клавиатуры, добавим к уже имеющейся части программного кода процедуру обработки нажатия кнопки [С] (сброс в первоначальную) готовность:
Private Sub Sbros_Click()
deystvie = "нет" ' стираем, возможно, указанное действие
Tablo.Caption = "0" ' на табло - ноль
Tablo.Tag = "" ' по умолчанию - вводится целое число
End Sub
Пользователь будет вводить число с клавиатуры используя клавиши с цифрами,
клавиши с точкой, а для перемены знака числа клавишу +/=. Редактировать
число с помощью клавиш Backspace и Пробел. Данные действия оперделим в
коде процедуры Form_KeyPress(), используя замечательный аргумент этой
процедуры - KeyAscii.
Поэтому если знать (или узнать) Ascii-коды клавиш, то понимание этой
процедуры не займёт много времени:
Private Sub Form_KeyPress(KeyAscii As Integer)
Select Case KeyAscii
Case 8 udalit_Click
Case 42, 43, 45, 47 ' теперь стало ясным почему индексы
Operacia_Click (47 - KeyAscii) ' следуют не по порядку?
Case 61 ' меняем знак
Plusmin_Click
Case Is > 47 ' вводим цифры
If KeyAscii < 58 Then knopka_Click (KeyAscii - 48)
Case 32 ' а здесь пробелом "чистим" табло ochistka_Click
End Select
End Sub
Данная процедура не позволяет отлавливать нажатие «точки», так как Ascii-
коды «точки» на малой цифровой клавиатуре отличны при разных раскладках.
Напишем соответствующий код в следующей процедуре.
Исход будет!
Однако мы до сих пор не указали заменители кнопок "сброса в первоначальное
состояние" и "равно". Для первого случая сложность заключается в
придумывании клавиши, а для другого - способа "отлавливания" нажатия
клавиши (я думаю ни у кого не возникнет сомнения в том, что нажатие клавиши
Enter будет соответствовать щелчку по кнопке равно).
Сбрасываем в начальное состояние клавишей Delete:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = 46 Then sbros_Click
' поскольку значения "точки" малой цифровой клавиатуры у KeyAscii не
одинаковые
' при различных раскладках, то "ловим" её с помощью KeyCode
If KeyCode = 110 Then tochka_Click
End Sub
Поймать нажатие клавиши Enter на кнопке можно следующим образом. Для этого вначале бросим на форму текстбокс. И спрячем его под границу будущего окна приложения (вначале увеличим высоту, затем поместим "туда" текстбокс и зададим высоту формы до её изменения). Изменим лишь свойства TabIndex на 1 и Name на Umno. Как вы уже скорее всего догадались нажатие по этому объекту будет выявлять нажатие клавиши Enter. Поэтому имеем такую процедуру:
Private Sub Umno_KeyPress(KeyAscii As Integer)
If KeyAscii = 13 Then Ravno_Click
End Sub
Однако, это сработает тогда, когда объект Umno имеет фокус. А что, если щёлкнуть по какой-то из кнопок? Тогда фокус переходит этой кнопке. И значит, нам надо вначале всех процедур обработки щелчков кнопок написать:
Umno.SetFocus
и тогда фокус будет всегда возвращаться на нужное нам место!
И, наконец, завершим наш проект, возвратясь почти к самому началу ...
"Покрасим" элементы управления!
Для этого процедуру Form_Load можно написать так:
Private Sub Form_Load()
Me.BackColor = RGB(50, 150, 250)
Sbros.BackColor = RGB(250, 50, 0)
Ochistka.BackColor = RGB(250, 75, 0)
Udalit.BackColor = RGB(250, 100, 0)
Ravno.BackColor = RGB(250, 125, 0)
Operacia(4).BackColor = RGB(150, 250, 250)
Operacia(2).BackColor = RGB(150, 250, 250)
Operacia(0).BackColor = RGB(150, 250, 250)
Operacia(5).BackColor = RGB(150, 250, 250)
End Sub
Четвёртый шаг или "делу время, а потехе – час!»
F5 - для проверки!