Проектирование и реализация интерфейса пользователя (меню на Си)Рефераты >> Программирование и компьютеры >> Проектирование и реализация интерфейса пользователя (меню на Си)
setcolor(LIGHTGRAY);
line(320-w/2,132,320+w/2,132); // стираем кусочек верхней линии
setcolor(BLACK);
line(132,135,319-w/2,135); // подрисовываем еще парочку линий
line(321+w/2,135,508,135);
outtextxy(320-w/2+5,131,"Радостная информация");
outtextxy(250,165,"Выбран пункт меню"); // выводим заголовок и станд. текст
setcolor(RED);
outtextxy(320-textwidth(text)/2,180,text); // выводим переменную text
setcolor(BLACK);
outtextxy(225,195,"Нажмите любую клавишу .");
ch=getch(); // Ждем нажатия клавиши
if (ch==0) ch=getch();
fillscreen(); // Перерисовываем экран
}
class Menu // класс меню представляет собой
{ // пункты меню и подменю
private:
char* name; // Имя пункта меню
Menu* next; // Указатель на следующий пункт
Menu* parent; // Указатель на родителя
Menu* sub; // Указатель на первый пункт подменю
unsigned int opened; // Пункт меню раскрыт
unsigned int selected; // Пункт меню выделен
public:
Menu(char* n) // Конструктор: создает пункт без подменю
{
name=n;
next=0;
sub=0;
parent=0;
opened=0;
selected=0;
}
Menu* AddItem(char* n) // Добавляет элемент следующим к текущему
{
next = new Menu(n);
next->SetParent(parent); // Родитель тот же
return next;
}
Menu* AddSubmenu(char* n) // Добавляет подменю к текущему
{
sub = new Menu(n);
sub->SetParent(this); // Родитель - текущий
return sub;
}
Menu* LevelUp() // Возвращает родителя текущего
{
if (parent!=0) return parent;
else return this;
}
void SetParent(Menu* m) // Устанавливает родителя
{
parent=m;
}
Menu* GetParent() // Возвращает родителя
{
return parent;
}
Menu* GetNext() // Возвращает указатель на седующий
{
return next;
}
Menu* GetSub() // Возвращает указатель на первый пункт
{ // подменю
return sub;
}
char* GetName() // Возвращает имя пункта
{
return name;
}
void PrintInfo() // Выводит информацию о пункте меню
{
cout<<name<<"\n";
}
void Select() // Выделяет данный пункт
{
selected=1;
}
void UnSelect() // Сбрасывает выделение
{
selected=0;
}
void OpenSubmenu() // Открывает подменю, если есть
{ // и выделяет там первый пункт
if (sub!=0)
{
opened=1;
sub->Select();
}
}
void CloseSubmenu() // Закрывает подменю, сбрасывая выделения
{ // и закрывая более "глубокие" открытые
opened=0; // подменю
Menu* tmp;
if (sub!=0)
{
tmp=sub;
while (tmp)
{
tmp->UnSelect();
tmp->CloseSubmenu();
tmp=tmp->GetNext();
}
}
}
int IsOpened() // Открыто ли здесь подменю?
{
return opened;
}
int IsSelected() // Выбран ли этот пункт?
{
return selected;
}
void paint(int x, int y) // Отрисовка системы подменю Главного Меню
{
Menu* tmp;
Menu* open=0; // Пункт с открытым подменю
int max_width=0, height, tw, num=0, i, xo,yo;
// max_width - максимальная длина названия пункта меню в пикселах
// height - суммарная высота пунктов в пикселах
// tw - рабочая переменная, смысловой нагрузки не несет
// num - количество пунктов
// i - рабочая переменная, смысловой нагрузки не несет
// xo, yo - координаты для отрисовки вложенного открытого подменю
tmp=this;
while (tmp) // Подсчитываем максимальную длину названий,
{ // кол-во пунктов
tw=textwidth(tmp->GetName());
if (tw > max_width) max_width=tw;
tmp=tmp->GetNext();
num++;
}
height = (textheight("A") + 4) * num + 6;
if (x+max_width+30 > 633) x=633 - max_width - 30;
if (y+height > 470) y=470 - height; // выполняем сдвиг,
// если меню выходит за границы
// экрана
draw_window(x,y,x+max_width+30,y+height);
// рисуем окошко, куда будем
// помещать пункты
tmp=this;
setcolor(BLACK);
x+=10;
y+=5;
while (tmp) // пока все не нарисуем
{
if (tmp->IsSelected()) // Пункт меню выделен - его надо инвертировать
{
setcolor(GREEN);
for (i=1;i<=textheight("A")+2;i++) // Высота: строка+2 пикс.
line(x-5,i+y-2,x+max_width+15,i+y-2);
setcolor(BLACK);
outtextxy(x,y,tmp->GetName());
// Если пункт открыт, это тоже надо нарисовать
if (tmp->IsOpened()) // но мы это сделаем позже
{
open=tmp->GetSub(); // сохраняем координаты и указатель
xo=x+max_width+23;
yo=y;
}
}
else outtextxy(x,y,tmp->GetName()); // рисуем обычный пункт
if (tmp->GetSub()) // рисуем "треугольничек", если у пункта
{ // есть подменю (в т.ч. и неоткрытое)
line(x+max_width+12,y+4,x+max_width+13,y+4);
line(x+max_width+12,y+3,x+max_width+12,y+5);
}
y+=textheight("A")+4;
tmp=tmp->GetNext();
// Нарисовав все текущее подменю, можем приступать
// к рисованию следующего вложенного. Если бы мы
// это сделали сразу, то потом дорисовывали бы
// текущее меню поверх уже нарисованного подменю
if (open) open->paint(xo,yo);
}
};
class MainMenu // Класс главное меню.
{
private:
Menu* list; // Список подменю
Menu* current; // Текущий пункт
Menu* selected; // Выделенный пункт
public:
MainMenu() // Конструктор
{
list=0;
current=0;
}
void AddItem(char* n) // Добавляет элемент следующим к текущему
{ // и делает новый элемент текущим
if (list==0)
{
selected = current = list = new Menu(n);
selected->Select();
}
else current = current->AddItem(n);
}
void AddSubmenu(char* n) // Добавляет подменю текущему и
{ // его первый элемент текущим
if (current!=0) current = current->AddSubmenu(n);
}
void LevelUp() // Делает текущим родителя текущего элемента
{
if (current!=0) current = current->LevelUp();
}
void paint() // Вывод системы меню на экран
{
Menu* tmp=list; // Рабочая переменная
int i, cur_x=18; // счетчик и координата вывода текста
setcolor(LIGHTGRAY); // Выводим полоску главного меню
for (i=0; i <= (textheight("A")+6); i++) // Высота: строка+6 пикс.
line(3,i+3,636,i+3);
setcolor(DARKGRAY); // Выводим тень полоски
line(5,i+3,638,i+3);
line(5,i+4,638,i+4);
line(637,4,637,i+4);
line(638,4,638,i+4);
setcolor(0); // Выводим пункты меню
while (tmp!=0 && cur_x<633) // Проверка на выход за полоску
{
if ( cur_x+textwidth (tmp->GetName()+18) < 633)
{
if (tmp==selected) // Пункт меню выделен - его надо инвертировать
{