На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила ЧаВо (FAQ) разделов Паскаля
В этом разделе разрешено создавать только темы, в которых описано РЕШЕНИЕ какой-либо общей проблемы, или описание какого-либо аспекта языка Паскаль.
Обсуждение уже созданных тем разрешено, но только конструктивное, например указание на ошибку или уточнение имеющегося текста.

Также читать Требования к оформлению статей
Модераторы: volvo877, Romtek
  
> Построение меню в программах, для курсовых и не только
    Построение меню в программах

    Мне часто приходится сталкиваться с программами, в которых студенты пытались построить нечто похожее на меню, и это было нечто... (слов не подобрать :) ). Построение меню занимало большую часть программы и алгоритм терялся в недрах гигантских программ.

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

    Более того, неприемлемо смешивание кода алгоритмов и интерфейса: в этом случае очень затрудняется поиск ошибок и нарушается строение программы.

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

    ExpandedWrap disabled
      uses crt;
      Type
         MenuType = (Vertical, Horizontal);
       
      const
         width = 9; { Максимальная длина элементов (букв) меню }
       
         Items1 = 5; { Количество элементов меню 1 }
         optText1: array [0..Items1-1] of string =
         ('Сложение',
          'Вычитание',
          'Деление',
          'Умножение',
          'Выход');
       
         Items2 = 3; { Количество элементов меню 2 }
         optText2: array [0..Items2-1] of string = (
          'item 1',
          'item 2',
          'item 3'
          );
       
         optNormal = LightGray; { цвет невыделенных элементов меню }
         optSelected = Yellow;  { цвет выделенных элементов меню }
       
      var
         X, Y,
         selected,  { Индекс элемента, который будет подсвечиваться в начале
                      программы }
         row: integer;
         _style: menuType;  { Указывает на тип меню: вертикальный (Vertical)
                              или горизонтальный (Horizontal) }
       
       
      { Эта процедура используется процедурой MenuOption для построения меню }
      procedure MakeMenu (optText: array of string; MaxItems: integer);
      var
         i, _X: byte;
      begin
           Y := row;
           _X := X;
           for i := 0 to MaxItems-1 do
           begin
                GoToXY (_X, Y);
                if i = selected then
                   TextColor (optSelected)
                else
                   TextColor (optNormal);
                write (optText[i]);
       
                If _style = Horizontal Then
                  inc (_X, width + 1)
                Else
                  inc (Y, 2);
           end;
      end;
       
      { выбираем нужный элемент меню этой функцией }
      function MenuOption (optText: array of string; MaxItems: integer): byte;
      var
         ch: char;
      begin
           selected := 0;
       
           If _style = Vertical then begin
             X := (80 - width) div 2;
             row := (25 - MaxItems) div 2;
           End
           Else
           Begin
             X := (80 - MaxItems * width) div 2;
             row := 2; { строчка, в которой будет находиться горизонтальное меню }
             GotoXY(1, row); ClrEol; { ... а для горизонтального - только строку
                                       где будет меню. }
           End;
       
           repeat
                 MakeMenu (optText, MaxItems);
       
                 ch := readkey;
                 if ch = #0 then
                    ch := readkey;
       
                 case ch of
                 #80, #77: {Down/Right}
                 begin
                      inc (Selected);
                      if Selected = MaxItems then
                         Selected := 0;
                      MakeMenu (optText, MaxItems);
                 end;
       
                 #72, #75: {Up/Left}
                 begin
                      dec (Selected);
                      if Selected < 0 then
                         Selected := MaxItems-1;
                      MakeMenu (optText, MaxItems);
                 end;
                 end;
           until ch = #13; {Enter}
       
           MenuOption := Selected + 1;
       
           TextColor (optNormal);
           If _style = Vertical Then
              clrscr;
      end;
       
      procedure Add;
      begin
      end;
       
      procedure Subtract;
      begin
      end;
       
      procedure Divide;
      begin
      end;
       
      procedure Multiply;
      begin
      end;
       
      var
        Option: byte; { номер выбранного пункта }
       
      begin
           clrscr;
       
           _style := Vertical; { вертикальное меню }
           Option := MenuOption (optText1, Items1);
       
           case option of
           1: Add;       { сложить числа }
           2: Subtract;  { вычесть числа }
           3: Divide;    { поделить числа }
           4: Multiply;  { умножить числа }
           5: exit;      { Выйти из программы }
           end;
       
           { вывести (если нужно) номер выбранного пункта }
           writeln ('Номер пункта: ', option);
           readln;
       
           _style := Horizontal; { горизонтальное меню }
           Option := MenuOption (optText2, Items2);
       
      end.

    Совместное авторство программы: © Romtek и volvo877. :)
    Сообщение отредактировано: Romtek -


      Бывает, что есть необходимость добавить пояснительный текст рядом с меню. В подавляющем количестве студенты пишут тогда следующий код:
      ExpandedWrap disabled
        begin
             GotoXY (1,2);
             writeln ('Для управления пользуйтесь клавишами стрелок:');
             GotoXY (1,4);
             writeln ('1 - сделать то-то...');
             writeln ('2 - сделать то-то...');
             writeln ('3 - сделать то-то...');
             writeln ('4- сделать то-то...'');
             writeln ('5 - сделать то-то...');
        end;
      Особенно неудобно в программах с большим текстом кода. В нём можно просто утонуть.
      Это дико неудобно возиться со множеством writeln, которые только отвлекают от сути, в то время как можно загрузить текст из текстового файла, заранее отредактированного в любом текстовом редакторе такой текст:
      ExpandedWrap disabled
        Для управления пользуйтесь клавишами стрелок:
         
        1 - сделать то-то...
        2 - сделать то-то...
        3 - сделать то-то...
        4 - сделать то-то...
        5 - сделать то-то...
      Не правда ли удобнее?

      Теперь рассмотрим процедуру, которая загрузит текст из отдельного текстового файла.
      ExpandedWrap disabled
        { Эта процедура используется процедурой TextWindow для загрузки текста из отдельного текстового файла. }
        procedure LoadText (fname: string);
        var F: text;
            str: string;
        begin
             Assign (F, fname);
             {$I-}
             Reset (F);
             {$I+}
             if IOresult = 0 then
             while Not EOF (F) do
             begin
                  readln (F, str);
                  writeln (str);
             end;
             Close (F);
        end;


      Эта процедура выведет текст в заданном регионе (окне) из текстового файла fn.
      ExpandedWrap disabled
        { Выводит текст в заданном регионе из текстового файла fn }
        procedure TextWindow (x1, y1, x2, y2: integer; fn: string);
        const
             TextColor = Cyan; { цвет фона региона }
        begin
             Window (x1, y1, x2, y2);
             TextBackground (TextColor);
             ClrScr;
         
             LoadText (fn);
         
             Window (1, 1, 80, 25);
             TextBackground (Black);
        end;
      Таким образом, задав нужные вам параметры, вы увидите текст рядом с меню.
      Например,
      ExpandedWrap disabled
             TextWindow (2, 2, 78, 7, 'strelki.txt');
             _style := Vertical; { вертикальное меню }
             Option := MenuOption (optText1, Items1);
      Здесь текст выводится в окне с границами 2, 2, 78, 7 из файла 'strelki.txt'.

      Примечание:
      Процедура TextWindow должна находиться перед построением меню! Иначе текста не будет видно.
        Вот вариант с использованием модуля menu_u:
        ExpandedWrap disabled
          uses crt, menu_u;
           
          const
             width1 = 9; { Максимальная длина элементов (букв) меню }
             Items1 = 5; { Максимальное количество элементов меню 1 }
             optText1: array [0..Items1-1] of string =
             ('Сложение',
              'Вычитание',
              'Деление',
              'Умножение',
              'Выход');
           
             width2 = 6; { Максимальная длина элементов (букв) меню }
             Items2 = 3; { Максимальное количество элементов меню 2 }
             optText2: array [0..Items2-1] of string = (
              'item 1',
              'item 2',
              'item 3'
              );
           
           
          procedure Add;
          begin
          end;
           
          procedure Subtract;
          begin
          end;
           
          procedure Divide;
          begin
          end;
           
          procedure Multiply;
          begin
          end;
           
          var
            Option: byte; { номер выбранного пункта }
           
          begin
               clrscr;
               TextWindow (2, 2, 78, 7, 'menu.txt');
               _style := Vertical; { вертикальное меню }
               Option := MenuOption (optText1, Items1, width1);
           
               case option of
               1: Add;       { сложить числа }
               2: Subtract;  { вычесть числа }
               3: Divide;    { поделить числа }
               4: Multiply;  { умножить числа }
               5: exit;      { Выйти из программы }
               end;
           
               { вывести (если нужно) номер выбранного пункта }
               writeln ('Номер пункта: ', option);
               readln;
           
               _style := Horizontal; { горизонтальное меню }
               Option := MenuOption (optText2, Items2, width2);
          end.



        Прикрепил файл с исходниками:
        1. Menudemo.pas - программа построения меню без использования модуля.
        2. Menu_t.pas - программа построения меню с модулем Menu_u.
          Menu_u.pas - модуль с основными функциями и процедурами для построения меню.
        Вариант b более предпочтителен, т.к. за счёт использования модуля гораздо легче ориентироваться в программе и отслеживать ошибки.
        Сообщение отредактировано: Romtek -

        Прикреплённый файлПрикреплённый файлmenudemo.ZIP (3.6 Кбайт, скачиваний: 292)
          Описание программы:

          За построение меню отвечает процедура MakeMenu - её вызывает функция MenuOption, которая возвращает результат в виде индекса выбранного пункта.

          Стиль меню определяется значением _style (Vertical/Horizontal) - то, как меню будет располагаться на экране.
          ExpandedWrap disabled
                 _style := Vertical; { вертикальное меню }

          Цвет нормальных элементов определяется константой optNormal, а цвет выделенных - optSelected.

          Остаётся всего-лишь определить названия элементов меню в optText,
          определить константу Items (количество элементов меню),
          определить константу width (максимальная длина букв самой длинной строки меню)
          и меню готово!

          Для вывода пояснительного текста рядом с меню можно воспользоваться процедурой TextWindow. 4 параметра означают координаты окна и строка - название файла, из которого загрузится описание для меню.

          Снимок экрана:
          Прикреплённый файлПрикреплённый файлmenudemo.PNG (6.64 Кбайт, скачиваний: 661)
          1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
          0 пользователей:


          Рейтинг@Mail.ru
          [ Script Execution time: 0,0993 ]   [ 15 queries used ]   [ Generated: 8.04.20, 01:20 GMT ]