Программирование. Принципы и практика использования C++ Исправленное издание, стр. 217
16.7. Добавление меню
Исследуем вопросы управления и взаимодействия, поднятые в разделе “Инверсия управления”, на примере создания меню для программы, рисующей линии. Для начала опишем меню, позволяющее пользователю выбирать цвет всех линий в переменной
linescolor_menustruct Lines_window:Window { Lines_window(Point xy,int w,int h,const string& title); Open_polyline lines; Menu color_menu; static void cb_red(Address,Address); // обратный вызов // для красной кнопки static void cb_blue(Address,Address); // обратный вызов // для синей кнопки static void cb_black(Address,Address); // обратный вызов // для черной кнопки // действия: void red_pressed() { change(Color::red); } void blue_pressed() { change(Color::blue); } void black_pressed() { change(Color::black); } void change(Color c) { lines.set_color(c); } // ...как и прежде...};Создание всех таких практически идентичных функций обратного вызова и функций “действия” — довольно утомительное занятие. Однако оно не вызывает никаких затруднений, а описание более простых средств выходит за рамки нашей книги. После щелчка на кнопке меню цвет линий изменяется на требуемый.
Определив член
color_menuLines_window::Lines_window(Point xy,int w,int h, const string&title):Window(xy,w,h,title), // ...как и прежде... color_menu(Point(x_max()–70,40),70,20,Menu::vertical,"color") { // ...как и прежде... color_menu.attach(new Button(Point(0,0),0,0,"red",cb_red)); color_menu.attach(new Button(Point(0,0),0,0,"blue",cb_blue)); color_menu.attach(new Button(Point(0,0),0,0,"black",cb_black)); attach(color_menu);}Кнопки динамически связываются с меню (с помощью функции
attach()Menu::attach()Экспериментируя с этой программой, мы решили, что нам необходимо выпадающее меню; т.е. мы не хотим фиксировать конкретное место на экране, в котором оно будет появляться. Итак, мы добавили кнопку Color menu. Когда пользователь щелкнет на ней, всплывет меню цвета, а после того как выбора меню снова исчезнет, и на экране отобразится кнопка.
Посмотрим сначала на окно, в которое добавлено несколько линий.


Мы видим новую кнопку Color menu и несколько черных линий. Щелкнем на кнопке Color menu, и на экране откроется меню.

Обратите внимание на то, что кнопка Color menu исчезла. Она не нужна, пока открыто меню. Щелкнем на кнопке blue и получим следующий результат.

Теперь линии стали синими, а кнопка Color menu вновь появилась на экране.
Для того чтобы достичь такого эффекта, мы добавили кнопку Color menu и модифицировали функцию “pressed”, настроив видимость меню и кнопки. Вот как выглядит класс
Lines_windowstruct Lines_window:Window { Lines_window(Point xy, int w, int h, const string& title );private: // данные: Open_polyline lines; // элементы управления окном: Button next_button; // добавляет (next_x,next_y) к линиям Button quit_button; // завершает работу программы In_box next_x; In_box next_y; Out_box xy_out; Menu color_menu; Button menu_button; void change(Color c) { lines.set_color(c); } void hide_menu() { color_menu.hide(); menu_button.show(); } // действия, инициирующие обратные вызовы: void red_pressed() { change(Color::red); hide_menu(); } void blue_pressed() { change(Color::blue); hide_menu(); } void black_pressed() { change(Color::black); hide_menu(); } void menu_pressed() { menu_button.hide(); color_menu.show(); } void next(); void quit(); // функции обратного вызова: static void cb_red(Address, Address); static void cb_blue(Address, Address); static void cb_black(Address, Address); static void cb_menu(Address, Address);