Проектируем калькулятор.

Оболочка PASCAL. Программа calcul.pas

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

Разработаем программу, реализующую простой калькулятор для работы с целыми числами и демонстрирующую использование программно организованных (виртуальных) кнопок.

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

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

Всю информацию запишем в файле кнопки.dat. Приведем возможный вид такого файла

 
сим- координаты    номер 
вол    кнопки      кнопки
  0  50 190  70 210  0
  1  50 160  70 180  1
  2  80 160 100 180  2
  3 110 160 130 180  3
  4  50 130  70 150  4
  5  80 130 100 150  5
  6 110 130 130 150  6
  7  50 100  70 120  7
  8  80 100 100 120  8
  9 110 100 130 120  9
  + 140 100 160 120 10
  - 140 130 160 150 11
  * 140 160 160 180 12
  C  80 190 100 210 13
  = 110 190 130 210 14
  / 140 190 160 210 15
После такой подготовительной работы можем начинать разработку самой программы. Прежде всего опишем необходимые переменные.
  Программа калькулятор; 
  Константы 
     N=15; { количество кнопок } 
     светлый = 255; { интенсивность светлого цвета } 
     темный  = 128; { интенсивность темного цвета } 
  Переменные коорд : массив [0..N,1..4] из целые; {координаты 
кнопок} 
     Данные : текст; {текстовый файл данных} 
     i,j,k : целые; {рабочие переменные для циклов} 
     число,предыдущее,операция: целые; 
     надпись : символы; {обозначение кнопок} 

Обратите внимание, что для надписей мы не формируем массив символов. Каждый символ для обозначения кнопки считываем с файла, выводим и в дальнейшая он не нужен, поэтому переменную надпись можем использовать для всех кнопок.

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

  Процедура Отобразить( k,верх,низ : целые ); 
  Начало 
    Позиция(коорд[k,1],коорд[k,2]); 
    Цвет(0,верх,0); 
    ЛинияК(коорд[k,3],коорд[k,2]); 
    ЛинияК(коорд[k,3],коорд[k,4]); 
    Цвет(0,низ,0); 
    ЛинияК(коорд[k,1],коорд[k,4]); 
    ЛинияК(коорд[k,1],коорд[k,2]); 
  конец;

Таким образом, рисовать кнопки мы уже умеем. Следующая проблема состоит в том, чтобы как-то обеспечить процесс ввода информации от пользователя к нашему калькулятору. Это можно осуществить двумя путями: с клавиатуры и от мышки. Выберем управления мышкой. Для этого напишем функцию, которая ожидает нажатия клавиши мышки и возвращает номер кнопки, которую нажал пользователь. Очевидно, что такая функция должна принимать целое значения. Самым сложным элементом этой функции есть проверка принадлежности точки ( i , j ), в которой была нажата клавиша мышки, к области, занятой кнопкой с номером k. Это проиллюстрировано на рисунке. Функция выполняет анализ событий в цикле, пока не будет нажата клавиша мышки на кнопке калькулятора. Номер этой кнопки функция возвращает как результат.

  Функция НомерКнопки : целые;
  Переменные раб: целые;
  Начало раб := -1; 
     Пока раб<0 выполнять 
       Начало 
         Событие(k,i,j); 
         Если k=2 то {если нажата клавиша мышки} 
           Для k:=0 до N выполнять 
           {если координаты указателя мышки в границах кнопки} 
           Если (i>коорд[k,1]) и (j>коорд[k,2]) 
            и (i<коорд[k,3]) и (j<коорд[k,4]) то 
             Начало 
               Отобразить(k,темный,светлый); {нажатая} 
               Задержка(10); {чтобы увидеть нажатие} 
               раб := k; {запомнить номер кнопки}
               Отобразить(k,светлый,темный); {отпущенная} 
             конец 
       конец;
     НомерКнопки:=раб 
  конец; 
Простейшей есть процедура обработки цифровой кнопки. Нужно просто число увеличить в 10 раз, прибавить введенную цифру и отобразить результат на индикаторе.
  Процедура ДобавитьЦифру(k:целые); 
  Начало 
    число:=число*10+k; 
    Позиция(55,72); 
    Вывести(число:11); 
  конец; 
Немного сложнее с кнопками операций. Настоящий калькулятор работает таким образом. Вводится первое число, запоминается операция потом вводится следующее число. Результат операции выводят при нажатии кнопки "=" или следующей операции. Напишем процедуру для выполнения операции.
  Процедура ВыполнитьОперацию; 
  Начало 
    Если операция>0 то 
    Начало 
      Выбор операция из 
        10: число:=предыдущее+число; 
        11: число:= предыдущее-число; 
        12: число:= предыдущее *число; 
        15: число:=round( предыдущее /число); 
      конец; 
      операция:=0; 
      Позиция(55,72); 
      Вывести(число:11) 
    конец 
  конец; 
Вся подготовительная работа сделана. Пишем главную программу.
  Начало
    { рисуем корпус калькулятора } 
    ЦветКисти(0,200,0); 
    Прямоугольник(40,60,170,220);
    { вводим данные }
    Присоединить( Данные, 'кнопки.dat' ); 
    Установить( Данные); 
    Для i:=0 до N выполнять 
      Начало 
        ВвестиСтр( Данные, надпись, коорд[i,1],коорд[i,2], 
               коорд[i,3],коорд[i,4]); 
        Позиция(коорд[i,1]+4,коорд[i,2]+2); 
        Вывести(надпись);
        { рисуем введенную кнопку }
        Отобразить(i,светлый,темный); 
      конец; 
    Закрыть( Данные ); 
    { рисуем табло индикатора }
    ЦветКисти(0,255,0); 
    Прямоугольник(50,70,160,90); число:=0; 
    предыдущее:=0; операция:=0; 
    ДобавитьЦифру(0); { просто выводит на индикатор нуль }
    Пока так выполнять 
      Начало 
        j:=НомерКнопки; 
      Выбор j из 
          0,1,2,3,4,5,6,7,8,9:
            { нажатая цифровая кнопка } 
            ДобавитьЦифру(j); 
          10,11,12,15: 
        Начало { нажатая кнопка операции }
              ВыполнитьОперацию; 
              операция:=j; 
              предыдущее:=число; 
              число:=0 
        конец; 
          13: 
        Начало { нажатая кнопк "С" } 
              число:=0; 
              предыдущее:=0; операция:=0; 
              ДобавитьЦифру(0) 
        конец; 
          14: { нажата кнопка "=" }
            ВыполнитьОперацию; 
      конец 
      конец 
  конец. 

Задания.