Текст программы
#include <iostream.h>
#include <conio.h>
#include <graphics.h>
void fillscreen()
{
int i;
setcolor(CYAN); // Заполняем экран цветом
for (i=0;i<480;i++)
line(0,i,639,i);
setcolor(6); // Выводим информацию о программе
outtextxy(20,453,"Курсовая работа студента группы АМ-112 Какорина Сергея");
outtextxy(20,465,"программа написана на языке Си++ с использованием принципов ООП");
}
void draw_window(int x1, int y1, int x2, int y2)
{ // Функция рисует окошко с тенью
int i; // фиксированного набора цветов
setcolor(LIGHTGRAY);
for (i=0; i<=y2-y1; i++)
line(x1,y1+i,x2,y1+i);
setcolor(BLACK);
line(x1+2,y1+2,x2-2,y1+2); // вывод рамки
line(x1+2,y2-2,x2-2,y2-2);
line(x1+2,y1+2,x1+2,y2-2);
line(x2-2,y1+2,x2-2,y2-2);
setcolor(DARKGRAY);
line(x1+2,y2+1,x2+2,y2+1); // вывод тени
line(x1+2,y2+2,x2+2,y2+2);
line(x2+1,y1+2,x2+1,y2+2);
line(x2+2,y1+2,x2+2,y2+2);
}
void ShowDialog(char* text) // демонстрирует небольшое диалоговое окно
{
int w,ch;
draw_window(130,130,510,240); // выводим окно
w=textwidth("Радостная информация")+10;
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) // Пункт меню выделен - его надо инвертировать
{
setcolor(GREEN);
for (i=0;i<=textheight("A")+2;i++) // Высота: строка+2 пикс.
line(cur_x-3,i+5,cur_x+textwidth(tmp->GetName())+3,i+5);
setcolor(BLACK);
outtextxy(cur_x,6,tmp->GetName());
// Если пункт открыт, это тоже надо нарисовать
if (tmp->IsOpened()) tmp->GetSub()->paint(cur_x,12+textheight("A"));
}
else outtextxy(cur_x,6,tmp->GetName()); // Выводим обычный пункт
cur_x+=textwidth(tmp->GetName())+18; // Увеличиваем позицию курсора
tmp=tmp->GetNext(); // Берем следующий пункт
}
}
}
Menu* FindSelection() // Поиск "активного" выделения
{ // по всей иерархии меню
Menu* tmp;
int found=0;
tmp=selected;
while (!found)
{
if (tmp->IsOpened()) tmp=tmp->GetSub(); // открыто - заходим
else if (tmp->IsSelected()) found=1; // выделено - нашли!
else tmp=tmp->GetNext(); // не выделено - дальше
}
return tmp;
}
int keypress(int ch) // Обработчик нажатий клавиш
{
Menu* tmp;
Menu* sel;
switch (ch)
{
case 0: // Спецклавиша, за ней идет другой код
{
ch=getch();
return keypress(ch);
}
case 75: // Нажата клавиша "Влево"
{ // реакция - если находимся в подменю
int open=0; // выходим из него, иначе - перемещаем
sel=FindSelection(); // выделение Главного меню
tmp=sel->GetParent();
if ((tmp->GetParent() != 0) && tmp)
{
tmp->CloseSubmenu();
fillscreen();
}
else
{
if (selected->IsOpened()) // Если мы не в главном меню
{ // то надо заново открыть подменю
selected->CloseSubmenu();
fillscreen();
open=1;
}
selected->UnSelect();
tmp=list;
while (tmp->GetNext() != selected && tmp->GetNext()!=0) tmp=tmp->GetNext();
selected=tmp;
selected->Select();
if (open) selected->OpenSubmenu();
}
paint(); // Перерисовываем меню
return 0;
}
case 72: // Нажата клавиша "Вверх"
{ // реакция - перемещение курсора вверх,
if (selected->IsOpened()) // если в Главном меню - открываем
{ // подменю
sel=FindSelection();
tmp = sel->GetParent();
tmp = tmp->GetSub();
if (tmp==sel)
while (tmp->GetNext()!=0) tmp=tmp->GetNext();
else
while (tmp->GetNext()!=sel) tmp=tmp->GetNext();
sel->UnSelect();
tmp->Select();
}
else keypress(13);
paint();
return 0;
}
case 77: // Нажата клавиша "Вправо"
{ // Реакция - если у данного пункта есть
int open=0; // подменю - открываем, если нет - переходим
sel=FindSelection(); // к след. пункту Главного меню.
// В Главном меню - просто переход.
if (sel->GetSub() && (sel != selected)) sel->OpenSubmenu();
else
{
if (selected->IsOpened())
{
selected->CloseSubmenu();
fillscreen();
open=1;
}
selected->UnSelect();
selected=selected->GetNext();
if (selected==0) selected=list;
selected->Select();
if (open) selected->OpenSubmenu();
}
paint(); // Перерисовываем меню
return 0;
}
case 80: // Нажата клавиша "Вниз"
{ // Просто перемещение, в Главном меню
if (selected->IsOpened()) // окрывает подменю
{
sel=selected->GetSub();
tmp=selected->GetSub();
while (tmp)
{
while (tmp && !tmp->IsOpened())
tmp=tmp->GetNext();
if (tmp) tmp=sel=tmp->GetSub();
}
tmp = sel;
while (!tmp->IsSelected())
tmp=tmp->GetNext();
tmp->UnSelect();
tmp=tmp->GetNext();
if (!tmp) tmp = sel;
tmp->Select();
}
else keypress(13);
paint();
return 0;
}
case 27: // Нажата клавиша "Escape"
{ // Реакция - выход и программы
return 1;
}
case 13: // Нажата клавиша "Enter"
{ // Реакция - открытие подменю, если есть,
Menu* tmp; // если нет - диалоговое окно с названием,
tmp=FindSelection(); // и закрываем все вплоть до Главного
if (tmp->GetSub())
{
tmp->OpenSubmenu();
paint();
}
else
{
selected->CloseSubmenu();
fillscreen();
paint();
ShowDialog(tmp->GetName());
paint();
}
return 0;
}
}
return 0;
}
void Run() // Основной цикл программы
{
int ch,rez=0;
fillscreen();
paint(); // Рисуем меню
while (rez!=1) // Пока не ключ выхода
{
ch=getch(); // Ждем нажатия кнопки
rez=keypress(ch); // Обрабатываем нажатие кнопки
}
}
};
void main()
{
MainMenu MyMenu; // Создание Главного Меню
MyMenu.AddItem("Файл"); // Формирование структуры меню
MyMenu.AddSubmenu("Новый");
MyMenu.AddItem("Открыть");
MyMenu.AddSubmenu("Программу");
MyMenu.AddItem("Проект");
MyMenu.LevelUp();
MyMenu.AddItem("Печать");
MyMenu.AddSubmenu("Программы");
MyMenu.AddItem("Проекта");
MyMenu.AddItem("Параметры страницы");
MyMenu.AddItem("Предварительный просмотр");
MyMenu.AddItem("Установки принтера");
MyMenu.LevelUp();
MyMenu.LevelUp();
MyMenu.AddItem("Правка");
MyMenu.AddSubmenu("Поиск");
MyMenu.AddSubmenu("Поиск вперед");
MyMenu.AddItem("Поиск назад");
MyMenu.AddItem("Поиск и замена");
MyMenu.LevelUp();
MyMenu.AddItem("Переход");
MyMenu.AddItem("Стили");
MyMenu.AddSubmenu("Основной текст");
MyMenu.AddItem("Комментарий");
MyMenu.AddItem("Заголовок");
MyMenu.AddItem("Ссылка");
MyMenu.LevelUp();
MyMenu.AddItem("Очистить");
MyMenu.AddItem("Вставить объект");
MyMenu.AddSubmenu("Из файла");
MyMenu.AddItem("Таблица");
MyMenu.AddItem("Диаграмма");
MyMenu.AddItem("Со сканнера");
MyMenu.AddItem("Сноска");
MyMenu.LevelUp();
MyMenu.AddItem("Выделить все");
MyMenu.LevelUp();
MyMenu.AddItem("Вид");
MyMenu.AddSubmenu("Документ");
MyMenu.AddSubmenu("Обычный");
MyMenu.AddItem("Разметка");
MyMenu.AddItem("Синтаксическая подсветка");
MyMenu.AddItem("Показывать ссылки");
MyMenu.LevelUp();
MyMenu.AddItem("Среда");
MyMenu.AddSubmenu("Панели инструментов");
MyMenu.AddItem("Окно отладчика");
MyMenu.AddItem("Окно процессора");
MyMenu.LevelUp();
MyMenu.LevelUp();
MyMenu.AddItem("Сервис");
MyMenu.AddSubmenu("Совместная работа");
MyMenu.AddSubmenu("Сверить версии");
MyMenu.AddItem("Сформировать апдейт");
MyMenu.AddItem("Сопроводительная информация");
MyMenu.AddItem("Подключить модуль");
MyMenu.AddItem("Список сотрудников");
MyMenu.LevelUp();
MyMenu.AddItem("Авто-подсказки");
MyMenu.AddItem("Макросы");
MyMenu.AddSubmenu("Список");
MyMenu.AddItem("Записать");
MyMenu.AddItem("Отредактировать");
MyMenu.LevelUp();
MyMenu.AddItem("Язык");
MyMenu.AddSubmenu("Изменить основной язык");
MyMenu.AddItem("Добавить язык к проекту");
MyMenu.LevelUp();
MyMenu.LevelUp();
MyMenu.AddItem("Отладка");
MyMenu.AddSubmenu("Компилировать");
MyMenu.AddItem("Точки останова");
MyMenu.AddSubmenu("Установить/сбросить");
MyMenu.AddItem("Перейти к следующей");
MyMenu.AddItem("Сбросить все");
MyMenu.LevelUp();
MyMenu.AddItem("Отследить значение переменной");
MyMenu.AddItem("Пошаговое выполнение");
MyMenu.AddSubmenu("Через");
MyMenu.AddItem("Внутрь");
MyMenu.LevelUp();
MyMenu.AddItem("Выполнить");
MyMenu.AddSubmenu("До курсора");
MyMenu.AddItem("Итерацию");
MyMenu.AddItem("До конца блока");
MyMenu.AddItem("До конца модуля");
MyMenu.LevelUp();
MyMenu.LevelUp();
MyMenu.AddItem("Справка");
MyMenu.AddSubmenu("О программе");
MyMenu.AddItem("Помощь по среде");
MyMenu.AddSubmenu("Содержание");
MyMenu.AddItem("Интерфейс");
MyMenu.AddItem("Меню");
MyMenu.AddItem("Горячие клавиши");
MyMenu.LevelUp();
MyMenu.AddItem("Помощь по языку");
MyMenu.AddSubmenu("Содержание");
MyMenu.AddItem("Поиск");
MyMenu.AddItem("Помощь по контексту");
MyMenu.LevelUp();
MyMenu.AddItem("Он-лайн");
MyMenu.AddSubmenu("Официальный сервер");
MyMenu.AddItem("Неофициальные страницы");
int driver=DETECT,mode=VGAHI; // Переводим комп в граф-режим
initgraph(&driver,&mode,"");
MyMenu.Run(); // Запускаем систему
closegraph(); // Переводим назад в текст. режим
}