Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.17.181.21] |
|
Сообщ.
#1
,
|
|
|
Построение меню в программах
Мне часто приходится сталкиваться с программами, в которых студенты пытались построить нечто похожее на меню, и это было нечто... (слов не подобрать ). Построение меню занимало большую часть программы и алгоритм терялся в недрах гигантских программ. Программа состоит из набора алгоритмов, данных и интерфейса. Но ошибаются те, которые считают, что интерфейс главнее. Это большое заблужение! Потому, что основную задачу выполняют именно алгоритмы, а не украшательства. Интерфейс же совсем не обязательная часть. Более того, неприемлемо смешивание кода алгоритмов и интерфейса: в этом случае очень затрудняется поиск ошибок и нарушается строение программы. Поэтому советую взять за основу эту программу, которая строит меню (горизонтальное или вертикальное) с управлением клавиш стрелок. Выбор пункта меню ведёт к отдельной подзадаче, каждая из которых оформлена в виде процедуры. В них вы будете выполнять действия, предусмотренные вашей программой. Я привёл пример для операций над числами. 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. |
Сообщ.
#2
,
|
|
|
Бывает, что есть необходимость добавить пояснительный текст рядом с меню. В подавляющем количестве студенты пишут тогда следующий код: begin GotoXY (1,2); writeln ('Для управления пользуйтесь клавишами стрелок:'); GotoXY (1,4); writeln ('1 - сделать то-то...'); writeln ('2 - сделать то-то...'); writeln ('3 - сделать то-то...'); writeln ('4- сделать то-то...''); writeln ('5 - сделать то-то...'); end; Это дико неудобно возиться со множеством writeln, которые только отвлекают от сути, в то время как можно загрузить текст из текстового файла, заранее отредактированного в любом текстовом редакторе такой текст: Для управления пользуйтесь клавишами стрелок: 1 - сделать то-то... 2 - сделать то-то... 3 - сделать то-то... 4 - сделать то-то... 5 - сделать то-то... Теперь рассмотрим процедуру, которая загрузит текст из отдельного текстового файла. { Эта процедура используется процедурой 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. { Выводит текст в заданном регионе из текстового файла 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; Например, TextWindow (2, 2, 78, 7, 'strelki.txt'); _style := Vertical; { вертикальное меню } Option := MenuOption (optText1, Items1); Примечание: Процедура TextWindow должна находиться перед построением меню! Иначе текста не будет видно. |
Сообщ.
#3
,
|
|
|
Вот вариант с использованием модуля menu_u:
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. Прикрепил файл с исходниками: Вариант b более предпочтителен, т.к. за счёт использования модуля гораздо легче ориентироваться в программе и отслеживать ошибки. Прикреплённый файлmenudemo.ZIP (3.6 Кбайт, скачиваний: 385) |
Сообщ.
#4
,
|
|
|
Описание программы:
За построение меню отвечает процедура MakeMenu - её вызывает функция MenuOption, которая возвращает результат в виде индекса выбранного пункта. Стиль меню определяется значением _style (Vertical/Horizontal) - то, как меню будет располагаться на экране. _style := Vertical; { вертикальное меню } Цвет нормальных элементов определяется константой optNormal, а цвет выделенных - optSelected. Остаётся всего-лишь определить названия элементов меню в optText, определить константу Items (количество элементов меню), определить константу width (максимальная длина букв самой длинной строки меню) и меню готово! Для вывода пояснительного текста рядом с меню можно воспользоваться процедурой TextWindow. 4 параметра означают координаты окна и строка - название файла, из которого загрузится описание для меню. Снимок экрана: Прикреплённый файлmenudemo.PNG (6.64 Кбайт, скачиваний: 758) |