Организация простого меню, вертикального или горизонтального.
Определим задачу: организовать меню, с возможностью выбора одного из пунктов с помощью курсорных
клавиш. Положение самого меню, и его внешний вид (горизонтальное или вертикальное), определяется в
программе.
Программа будет состоять из функции MainMenu и основного кода, обрабатывающего результат выбора.
Чем должна делать функция MainMenu?
- Задавать пункты меню и выводить их на экран в нужном порядке в нужном месте;
- Показывать какой пункт меню выбрал пользователь;
- Скрывать пункты меню, выбранные ранее;
- Давать возможность выбрать нужный пункт меню с помощью клавиатуры.
Так, как необходимо хранить в памяти названия пунтов меню и их расположение на экране, то
обыкновенным массивом не обойтись, нужно определить свой тип данных для такого массива.
Type TMenu = record
X,Y : Byte;
S : String[20];
End;
где X и Y - координаты, в которых нужно выводить конкретный пункт меню, а S - его название.
Теперь можно определить переменную Menu, как массив типа TMenu, и задать его:
Menu[0].S := 'item 0'; Menu[0].X := 20; Menu[0].Y := 5;
Menu[1].S := 'item 1'; Menu[1].X := 20; Menu[1].Y := 6;
Menu[2].S := 'item 2'; Menu[2].X := 20; Menu[2].Y := 7;
Menu[3].S := 'item 3'; Menu[3].X := 20; Menu[3].Y := 8;
Menu[4].S := ' exit '; Menu[4].X := 20; Menu[4].Y := 9;
Для рисования самого меню, без выбранных пунктов определим процедуру DrawMenu:
Procedure DrawMenu;
Var I : Byte;
Begin
For I := 0 To MaxMenuItem Do
Begin
GotoXY(Menu[I].X, Menu[I].Y);
Write(Menu[I].S);
End;
End;
где MaxMenuItem - максимальное число пунктов в меню. Последний пункт, определяем как выход.
Так как выбранный пункт должен явно отличаться от всех остальных пунктов меню, будем делать его
инверсным. То есть цвет фона и цвет тона нужно поменять местами. Для этого из переменной TextAttr
выделяем нужные цвета TC и TB для раскраски выбранного пункта.
TC := TextAttr mod 16;
TB := TextAttr div 16;
Попробуем нарисовать выбранный пункт меню, используя отдельную процедуру:
Procedure Select (I:Byte);
Begin
TextBackground(TC); TextColor(TB);
GotoXY(Menu[I].X, Menu[I].Y);
Write(Menu[I].S);
TextBackground(TB); TextColor(TC);
End;
Как видим, способ вывода ничем не отличается от процедуры DrawMenu. Единственное отличие - процедура
рисует один пункт меню, номер которого является входным параметром. Для инверсии цвета, введены строчки:
TextBackground(TC); TextColor(TB); Перед выходом из процедуры, цвета восстанавливаются:
TextBackground(TB); TextColor(TC);
Процедура обратного выбора DeSelect, или сокрытия выбранного пункта меню полный аналог Select:
Procedure DeSelect (I:Byte);
Begin
TextBackground(TB); TextColor(TC);
GotoXY(Menu[I].X, Menu[I].Y);
Write(Menu[I].S);
TextBackground(TB); TextColor(TC);
End;
Единственное отличие - первая строчка похожа на последнюю. Их можно вообще не писать, но я оставил так,
для красоты кода.
Основной этап подготовки функции завершен. Нужно подготовиться к выводу на экран и обработки клавиатуры.
DrawMenu;
Sel := R_Select;
Select(Sel);
Sel - выбранный пункт меню. R_Select - входной параметр функции MainMenu, он нужен для того, чтобы
оставить выбранным тот пункт, который был выбран в момент обработки события. Так курсор не "прыгает"
на первый пункт.
Напишем обработчик клавиатуры. Кроме тупого перебора пунктов меню, предоставим пользователю возможность
выбрать пункт клавишей Enter и выйти из меню клавишей Esc.
Run := False;
While Not Run Do Begin
Case ReadKey Of
#13 : Run := True;
#27 : Begin
Run := True;
Sel := MaxMenuItem;
End;
#0 : Case ReadKey Of
#72 : Begin
DeSelect(Sel);
If Sel = 0
Then Sel := MaxMenuItem
Else Sel := Sel - 1;
Select(Sel);
End;
#80 : Begin
DeSelect(Sel);
If Sel = MaxMenuItem
Then Sel := 0
Else Sel := Sel + 1;
Select(Sel);
End;
End;
End;
End;
MainMenu := Sel;
Run - пользователь закончил работу с меню и сделал свой выбор. Нажал Enter или Esc. #13 и #27 - коды этих клавиш.
Курсорные клавиши возвращают расширенный код. По этому при обнаружении #0 используем вложенный Case.
#72 и #80 коды клавиш вверх и вниз.
Для того, чтобы сдвинуться в указанном направлении, надо спрятать выбранный ранее пункт меню, изменить
переменную Sel так, чтобы она указывала на новый пункт и не выходила за пределы меню. Показать новый пункт.
Чтобы вертикальное меню превратить в горизонтальное, надо изменить координаты в массиве Menu и коды клавиш #72 и #80.
Теперь легко описать действия в зависимости от выбранного пункта в основной программе:
ClrScr;
TextBackground(Blue);
TextColor(LightGreen);
Ret := 0;
Repeat
Ret := MainMenu(Ret);
Case Ret Of
0: Begin
WriteLn('Выбран пункт: ', Ret);
WriteLn('... нажми клавишу ...');
ReadLn;
End;
1: Begin
WriteLn('Выбран пункт: ', Ret);
WriteLn('... нажми клавишу ...');
ReadLn;
End;
2: Begin
WriteLn('Выбран пункт: ', Ret);
WriteLn('... нажми клавишу ...');
ReadLn;
End;
3: Begin
WriteLn('Выбран пункт: ', Ret);
WriteLn('... нажми клавишу ...');
ReadLn;
End;
Else Begin
WriteLn('Выход из программы');
WriteLn('... нажми клавишу ...');
ReadLn;
End;
End; {case Ret}
Until Ret = MaxMenuItem;
TextBackground(Black);
TextColor(LightGray);
ClrScr;
Пахтусов Сергей, 07.03.2006
Лень учить? Смотри pascal на видео |