Шрифт:
Интервал:
Закладка:
Система графического пользовательского интерфейса (и операционная система) может использоваться программами, написанными на разных языках, но они не могут навязывать всем пользователям стиль языка С++. В частности, ей ничего не известно о наших классах Simple_window и Button. Фактически она вообще ничего не знает о классах и их членах. Тип, требуемый для обратного вызова функции, выбирается так, чтобы его можно было использовать на самых низких уровнях программирования, включая язык C и ассемблер. Функция обратного вызова не возвращает значений и принимает в качестве аргументов два адреса. Мы можем объявить функцию-член так, чтобы она подчинялась этим требованиям.
static void cb_next(Address, Address); // обратный вызов для
// next_button

Эту информацию можно использовать следующим образом:
void Simple_window::cb_next(Address,Address pw)
// вызов Simple_window::next() для окна, расположенного по адресу pw
{
reference_to<Simple_window>(pw).next();
}
Вызов функции reference_to<Simple_window>(pw) сообщает компьютеру, что адрес, хранящийся в переменной pw, должен интерпретироваться как адрес объекта класса Simple_window; иначе говоря, мы можем использовать значение reference_to<Simple_window>(pw) как ссылку на объект класса Simple_window. В главах 17-18 мы еще вернемся к вопросам адресации памяти. Определение функции reference_to (кстати, совершенно тривиальное) мы покажем в разделе Д.1. А пока просто рады наконец получить ссылку на наш объект класса Simple_window и непосредственный доступ к нашим данным и функциям, которые собирались использовать. Теперь поскорее выходим из этого системно-зависимого кода, вызывая нашу функцию-член next().

• Функция cb_next() превращает системные соглашения об обратных вызовах в вызов обычной функции-члена next().
• Функция next() делает то, что мы хотели (ничего не зная о запутанном механизме обратного вызова).

• Мы определяем наш объект класса Simple_window.
• Конструктор класса Simple_window регистрирует свою кнопку next_button в системе графического пользовательского интерфейса.
• Когда пользователь щелкает на изображении объекта next_button на экране, графический пользовательский интерфейс вызывает функцию cb_next().
• Функция cb_next() преобразует низкоуровневую информацию системы в вызов нашей функции-члена next() для нашего окна.
• После щелчка на кнопке функция next() выполняет требуемое действие.
Это довольно сложный способ вызвать функцию. Однако помните, что мы работаем с основным механизмом, обеспечивающим взаимодействие мыши (или другого устройства) с программой. В частности, следует иметь в виду следующие обстоятельства.
• Как правило, на компьютере одновременно выполняется много программ.
• Программа создается намного позже операционной системы.
• Программа создается намного позже библиотеки графического пользовательского интерфейса.
• Программа может быть написана на языке, отличающемся от того, который используется в операционной системе.
• Описанный метод охватывает все виды взаимодействий (а не только щелчок на кнопке).
• Окно может иметь много кнопок, а программа может иметь много окон.
Однако, поняв, как вызывается функция next(), мы фактически поймем, как обрабатывается каждое действие в программе, имеющей графический пользовательский интерфейс.
16.3.2. Цикл ожидания

// создаем и/или манипулируем некоторыми объектами, изображаем
// их в окне
win.wait_for_button(); // работа программы возобновляется с этой
// точки
// создаем и/или манипулируем некоторыми объектами
На самом деле это просто. Сначала определим функцию wait_for_button().
void Simple_window::wait_for_button()
// модифицированный цикл событий:
// обрабатываем все события (по умолчанию),
// выходим из цикла, когда переменная button_pushed становится
// true
// это позволяет рисовать без изменения направления потока
// управления
{
while (!button_pushed) Fl::wait();
button_pushed = false;
Fl::redraw();
}
