Проектирование и реализация интерфейса пользователя (меню на Си)
Рефераты >> Программирование и компьютеры >> Проектирование и реализация интерфейса пользователя (меню на Си)

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) // Пункт меню выделен - его надо инвертировать

{


Страница: