Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Меню и файлы

Автор: Sensitive 7.11.2007 23:23

Здравствуйте.
У меня такой вопрос. Есть меню из 3-х пунктов. Если нажимается первый пункт, то должно появиться следующее меню, где также можно выбирать пункты второго меню. Содержимое второго меню хранится в файле. То есть при нажатии на первый пункт главного меню я вывожу пункты второго меню из файла. Как сделать, чтобы из этих (выведенных из файла) пунктов также можно было выбирать... или это невозможно?
Спасибо заранее за помощь.

Автор: Tan 7.11.2007 23:30

Есть же оператор case(x), что тебе его мешает использовать для того, чтобы осуществить выбор.

Автор: Sensitive 8.11.2007 0:00

Цитата(Tan @ 7.11.2007 19:30) *

Есть же оператор case(x), что тебе его мешает использовать для того, чтобы осуществить выбор.


с case у меня получается работать только если пункты меню заданы стринговской константой. А если я их вывела из файла, то не могу понять как использовать case в данном случае...

Автор: volvo 8.11.2007 0:05

Sensitive, для этого надо максимально отделить функцию отображения меню от всего остального. То есть, есть какой-то массив строк, есть функция

function get_menu(const s_arr: array of string): integer;
, которая отображает этот массив и подсвечивает нужный элемент в зависимости от выбора пользователя. Когда нажат Enter - возвращается индекс выбранного значения. Все. Больше эта функция не должна быть привязана ни к чему. Только так ты сможешь обеспечить работу с одинаковой легкостью с меню любой вложенности.

Примеры я выкладывал у себя на сайте: http://volvo71.narod.ru/menus.htm

Автор: Sensitive 8.11.2007 0:09

Спасибо, я попробую.

Автор: Sensitive 9.11.2007 23:14

посмотрела меню на сайте. взяла пока что тупо меню оттуда... вот получается вывожу главное меню, и подменю. А дальше мне еще нужно выводить подменюшки-там где "Просмотр данных" и "Добавление данных"(код ниже)...не знаю как это сделать, и как отделить подпрограмму отрисовки меню не поняла (как говорил Volvo). Вот мой код, посмотрите плиз.

uses crt;
Type MenuType=(Vertical);
const
width = 12;
nItems = 3;
optNormal = LightGray;
optSelected = Yellow;
s: array [1..3] of string=('termini','podprogrammi','exit');
t: array[1..3] of string=('Prosmotr dannih','Dobavlenie dannih','Vozvrat v menu');
var
X, Y,
selected,
row: integer;
_style: MenuType;

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 ]);
inc (Y, 2);
end;
end;
function MenuOption (var optText: array of string; MaxItems: integer): byte;
var
ch: char;
begin
selected := 0;

X := (80 - width) div 2;
row := (25 - MaxItems) div 2;
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;
end;
until ch = #13;

MenuOption := Selected + 1;
TextColor (optNormal);
clrscr;
end;
Procedure Prosmotr;
var g:text; s:string[20]; i:byte;
begin
assign(g,'termini.txt');
reset(g);
while not eof(g) do
begin
readln(g,s);
{gotoxy(14,whereY+1);}
writeln(s);
end;
end;

Procedure ShowMenu(s:array of string);
var
Option,i: byte;
begin
_style := Vertical;
repeat
clrscr;
Option := MenuOption (s, nItems);

case option of
1:showMenu(t);
{ 2: ...;
3: ...; }
end
until Option = nItems;
end;

begin
showMenu(s);
end.

Автор: volvo 10.11.2007 0:37

Да хоть еще 10 уровней... Смотри, я добавил тип TProcedure, и еще один уровень меню (который ничего не делает, только отображается, но на него очень просто повесить какие-то действия) на "Prosmotr dannih":

Прикрепленный файл  submenu.pas ( 2.34 килобайт ) Кол-во скачиваний: 488


Разберешься?

Автор: Sensitive 10.11.2007 3:56

Да, volvo, с этим поняла. И действительно можно сделать теперь много уровней меню-очень помог. Но... Мне получается сами пункты меню ("Просмотр данных" например) нужно выводить из файла, то есть я их никак не введу в строковую константу... как мне быть? выводить я их думала процедурой Prosmotr;

Procedure Prosmotr;
var g:text; s:string[20]; i:byte;
begin
assign(g,'termini.txt');
reset(g);
while not eof(g) do
begin
readln(g,s);
{gotoxy(14,whereY+1);}
writeln(s);
end;
end;

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

Автор: volvo 10.11.2007 4:33

А как, прости, ты будешь знать, какое ДЕЙСТВИЕ выполнять при выборе того или иного пункта меню, прочитанного из файла? Просто прочесть строки из файла и отобразить их в меню - без проблем:

const
max_lines_in_menu = 15;
type
myString = string;

PStrArr = ^strArr;
strArr = array[1 .. max_lines_in_menu] of myString;

function Prosmotr(f_name: string; var size: integer): PStrArr;
var
f: text;
s: string;
i: integer;
p: PStrArr;
begin
assign(f, f_name);
reset(f);
readln(f, size); { <--- Первая строка файла - количество строк в менюшке }
getmem(p, size * sizeof(myString)); { <--- берем столько памяти, сколько нужно для хранения }
i := 1;
while not eof(f) do begin
readln(f, s);
p^[i] := s; inc(i); { <--- заполняем массив }
end;
close(f);
Prosmotr := p;
end;


procedure do_termini;
var
p: PStrArr;
size: integer;
begin
p := Prosmotr('termini.txt', size); { <--- прочли файл в дин. память }
ShowMenu(p^, t_proc); { <--- отрисовали меню (вот только с ДЕЙСТВИЯМИ - непонятно) }
FreeMem(p, size * sizeof(myString)); { <--- освободили память }
end;


Файл: Прикрепленный файл  termini.txt ( 55 байт ) Кол-во скачиваний: 468


Если у тебя возник вопрос о том, что в некоторых подменюшках может быть по 3, а в некоторых - и по 5 элементов, то это тоже не проблема, достаточно не брать nItems в ShowMenu из константы, а передавать еще одним параметром (как раз в приведенном выше коде Prosmotr заодно возвращает и длину массива строк).

Только вот с массивом Proc - непонятно, что делать... Откуда ты (вернее, программа, читающая файл 'termini.txt') будет знать, что по нажатию на первый пункт меню надо открыть еще один файл? Сейчас-то пока массив Proc для прочитанного из файла меню задается вручную... Ну, извратиться, конечно можно (если надо - говори, я попробую объяснить, как это преодолеть, есть кое-какая идея), но стоит ли оно таких ухищрений?

Автор: Sensitive 10.11.2007 6:09

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