Главная :: Программы для программирования :: wxWidgets :: Перевод книги "Programming with wxWidgets" :: Глава II – Начало. Часть 2
Иисус изменил твою жизнь. Сохранить(Да/Нет) ?

Глава II – Начало. Часть 2

Класс фрейма

Рассмотрим класс фрейма MyFrame. Фрейм является основным окном, которое содержит все остальные окна и обычно имеет меню и строку состояния. Вот простейший пример объявления класса для фрейма, которое мы разместим после объявления MyApp:

// Объявляем класс главного окна class MyFrame : public wxFrame { public: //Конструктор MyFrame(const wxString& title); // Обработчики сообщений void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); private: // Этот класс перехватывает сообщения DECLARE_EVENT_TABLE() };

Наш класс для фрейма содержит конструктор, два обработчика сообщений (связывающих пункты меню с C++ кодом) и макрос, который сообщает, что класс содержит обработчики сообщений.

Обработчики сообщений

Как вы уже знаете, функции обработки сообщений в MyFrame не являются виртуальными и не должны быть виртуальными. Тогда как же они вызываются? Ответ расположен в следующей таблице сообщений:

// Таблица сообщений для MyFrame BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) EVT_MENU(wxID_EXIT, MyFrame::OnQuit) END_EVENT_TABLE()

Таблица сообщений, помещенная в файл с реализацией класса, говорит wxWidgets каким образом связываются сообщения, поступающие от пользователя, и методы класса.В указанной выше таблице нажатие кнопки мыши на пунктах меню с идентификаторами wxID_EXIT и wxID_ABOUT направляется функциям MyFrame::OnQuit и MyFrame::OnAbout соответственно. Макрос EVT_MENU является одним из многих возможных макросов таблицы сообщений, которые вы можете использовать, чтобы указать wxWidgets какие типы сообщений направлять в функцию. Идентификаторы, используемые в нашем примере, являются предопределенными, но чаще всего вы должны вводить свои собственные с помощью перечислений (enum), констант или директив препроцессора (#define).Этот тип таблицы сообщений называется статическим, то есть не может быть изменен в процессе выполнения программы. В следующей главе мы расскажем, как создавать динамические обработчики сообщений.Пока мы разбираемся с таблицами сообщений, давайте посмотрим на две функции, которые у насиспользуются для обработки сообщений.

void MyFrame::OnAbout(wxCommandEvent& event) { wxString msg; msg.Printf(wxT("Hello and welcome to %s"), wxVERSION_STRING); wxMessageBox(msg, wxT("About Minimal"), wxOK | wxICON_INFORMATION, this); } void MyFrame::OnQuit(wxCommandEvent& event) { // Уничтожаем фрейм Close(); }

Метод 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.

Создание фрейма

Наконец, у нас есть конструктор для фрейма, который инициализирует иконку для приложения, меню и строку состояния.

#include "mondrian.xpm" MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title) { // Устанавливаем иконку для фрейма SetIcon(wxIcon(mondrian_xpm)); // Создаем меню wxMenu *fileMenu = new wxMenu; // Добавляем пункт "About" (о приложении), который // должен показывать маленькую помощь wxMenu *helpMenu = new wxMenu; helpMenu->Append(wxID_ABOUT, wxT("&About...\tF1"), wxT("Show about dialog")); fileMenu->Append(wxID_EXIT, wxT("E&xit\tAlt-X"), wxT("Quit this program")); // Теперь добавляем созданное меню в строку меню... wxMenuBar *menuBar = new wxMenuBar(); menuBar->Append(fileMenu, wxT("&File")); menuBar->Append(helpMenu, wxT("&Help")); // ... и присоединяем к фрейму SetMenuBar(menuBar); // Создаем строку состояния для красоты CreateStatusBar(2); SetStatusText(wxT("Welcome to wxWidgets!")); }

Данный конструктор вызывает конструктор родительского класса с указанием родительского окна (NULL означает его отсутствие), идентификатором этого окна и заголовком. Вместо идентификатора внашем случае передается значение wxID_ANY, которое говорит wxWidgets, что идентификатор должен быть создан библиотекой самостоятельно. Таким образом, конструктор создает настоящее окно с помощью перенаправления запроса на создание к родительскому классу.Маленькие изображения и иконки могут быть помещены в программу с помощью мультиплатформенного формата XPM. Файл XPM представляет из себя обычный C++ код, а потому может быть включен так, как показано в нашем примере. Строка с SetIcon создает иконку в стеке, используя C++ переменную mondrian_xpm (определенную в файле mondrian.xpm) и связывает полученную иконку с фреймом.Далее создается меню. При добавлении элементов меню указывается их идентификатор (например, стандартный идентификатор wxID_ABOUT, как в нашем случае), текстовую метку для элемента меню и строка помощи, которая может быть показана в строке состояния. Внутри каждой метки можно поместить мнемоники (указатели для вызова пункта с клавиатуры) с помощью предшествующего букве амперсанда (&), а также указать акселератор, отделяя его от сообщения с помощью символа табуляции (\t). Мнемоники позволяют пользователю выбрать пункт меню с помощью нажатия соответствующей клавиши во время навигации по меню. Акселератор — это комбинация клавиш (например, Alt+X), которая может быть использована для выполнения действия вообще без вызова меню.В конце конструктор создает строку статуса, состоящую из двух полей и расположенную снизу фрейма. Для первого поля устанавливается значение Welcome to wxWidgets!