Рассмотрим класс фрейма MyFrame. Фрейм является основным окном, которое содержит все остальные окна и обычно имеет меню и строку состояния. Вот простейший пример объявления класса для фрейма, которое мы разместим после объявления MyApp:
Наш класс для фрейма содержит конструктор, два обработчика сообщений (связывающих пункты меню с C++ кодом) и макрос, который сообщает, что класс содержит обработчики сообщений.
Как вы уже знаете, функции обработки сообщений в MyFrame не являются виртуальными и не должны быть виртуальными. Тогда как же они вызываются? Ответ расположен в следующей таблице сообщений:
Таблица сообщений, помещенная в файл с реализацией класса, говорит wxWidgets каким образом связываются сообщения, поступающие от пользователя, и методы класса.В указанной выше таблице нажатие кнопки мыши на пунктах меню с идентификаторами wxID_EXIT и wxID_ABOUT направляется функциям MyFrame::OnQuit и MyFrame::OnAbout соответственно. Макрос EVT_MENU является одним из многих возможных макросов таблицы сообщений, которые вы можете использовать, чтобы указать wxWidgets какие типы сообщений направлять в функцию. Идентификаторы, используемые в нашем примере, являются предопределенными, но чаще всего вы должны вводить свои собственные с помощью перечислений (enum), констант или директив препроцессора (#define).Этот тип таблицы сообщений называется статическим, то есть не может быть изменен в процессе выполнения программы. В следующей главе мы расскажем, как создавать динамические обработчики сообщений.Пока мы разбираемся с таблицами сообщений, давайте посмотрим на две функции, которые у насиспользуются для обработки сообщений.
Метод MyFrame::OnAbout показывает небольшое сообщение пользователю, когда тот выбирает из меню пункт About. Функция wxMessageBox принимает в качестве аргументов текст сообщения, заголовок окна, комбинацию стилей и указатель на родительское окно.Как это указано в таблице сообщений, функция MyFrame::OnQuit вызывается, когда пользователь выбирает в меню пункт Quit. Наш обработчик данного сообщения вызывает метод Closeдля уничтожения фрейма и таким образом завершает работу приложения, так как программасостоит всего из одного фрейма. На самом деле метод Close не уничтожает приложение, он просто генерирует сообщение wxEVT_CLOSE_WINDOW, обработчик которого по умолчанию уничтожает фрейм, используя для этого метод wxWindow::Destroy.Существуют другие пути для завершения работы приложения — пользователь может щелкнуть на кнопке закрытия, расположенной на фрейме, или выбрать пункт Close из системного меню (или меню оконного менеджера среды запуска). Когда метод OnQuit вызывается в этихслучаях? Ну если честно, то он не вызывается. В указанных случаях wxWidgets посылает фрейму сообщение wxEVT_CLOSE_WINDOW через вызов функции Close (подобно тому, как это делаем мы в методе OnQuit). wxWidgets по умолчанию перехватывает это сообщение и уничтожает окно. Ваше приложение может переопределить данное поведение и, например, запрашивать подтверждение у пользователя перед закрытием. Обратитесь к Главе 4 Окна за дополнительной информацией.В нашем примере этого делать не требовалось, но большая часть приложений реализует функцию OnExit в классе приложения для корректной очистки структур данных перед выходом. Обратите внимание, что эта функция вызывается только если OnInit возвратила true.
Наконец, у нас есть конструктор для фрейма, который инициализирует иконку для приложения, меню и строку состояния.
Данный конструктор вызывает конструктор родительского класса с указанием родительского окна (NULL означает его отсутствие), идентификатором этого окна и заголовком. Вместо идентификатора внашем случае передается значение wxID_ANY, которое говорит wxWidgets, что идентификатор должен быть создан библиотекой самостоятельно. Таким образом, конструктор создает настоящее окно с помощью перенаправления запроса на создание к родительскому классу.Маленькие изображения и иконки могут быть помещены в программу с помощью мультиплатформенного формата XPM. Файл XPM представляет из себя обычный C++ код, а потому может быть включен так, как показано в нашем примере. Строка с SetIcon создает иконку в стеке, используя C++ переменную mondrian_xpm (определенную в файле mondrian.xpm) и связывает полученную иконку с фреймом.Далее создается меню. При добавлении элементов меню указывается их идентификатор (например, стандартный идентификатор wxID_ABOUT, как в нашем случае), текстовую метку для элемента меню и строка помощи, которая может быть показана в строке состояния. Внутри каждой метки можно поместить мнемоники (указатели для вызова пункта с клавиатуры) с помощью предшествующего букве амперсанда (&), а также указать акселератор, отделяя его от сообщения с помощью символа табуляции (\t). Мнемоники позволяют пользователю выбрать пункт меню с помощью нажатия соответствующей клавиши во время навигации по меню. Акселератор — это комбинация клавиш (например, Alt+X), которая может быть использована для выполнения действия вообще без вызова меню.В конце конструктор создает строку статуса, состоящую из двух полей и расположенную снизу фрейма. Для первого поля устанавливается значение Welcome to wxWidgets!