Шаг 3.
Библиотека OWL.
Создание собственного окна

    На этом шаге мы рассмотрим создание собственных окон.

    Хотя простейшая OWL-программа из предыдущего шага создает полноценное работающее основное окно, оно не способно взаимодействовать с пользователем, кроме как через элементы управления, и может только перемещаться, менять размер, сворачиваться и разворачиваться.

    Чтобы сделать OWL-приложение полезным, нужно заставить объект приложения создать окно более сложное, чем то, которое создается по умолчанию. Для этого необходимо переписать виртуальную функцию InitMainWindow() класса TApplication, как показано в примере ниже.

    По умолчанию, функция InitMainWindow() создает объект класса TFrameWindow (т.е. окно) с указанным заголовком. Чаще всего текст этой функции содержит вызов функции SetMainWindow(), которая определяет, какое окно должно использоваться в качестве главного.


    Пример. Демонстрация создания класса приложения и задания класса основного окна.
#include <owl\applicat.h>
#include <owl\framewin.h>
// Класс приложения.
class TApp : public TApplication
{
  public:
	 TApp() : TApplication() {};
	 void InitMainWindow();
};
// Класс основного окна.
class TWndw : public TFrameWindow
{
  public:
	 TWndw(TWindow *parent, const char far *title):
			 TFrameWindow(parent, title) {}
};
// TApp::InitMainWindow().
// Эта функция создает основное окно приложения.
void TApp::InitMainWindow()
{
  //Создает новое главное окно.
  TFrameWindow *wndw = new TWndw(0, "Окно 2");
  //Определяет, какое окно использовать в качестве главного.
  SetMainWindow(wndw);
}

int OwlMain (int, char*[])
{
  return TApp().Run() ;
} 
Текст этой программы можно взять здесь.

    Когда вы запустите эту программу, то увидите окно, показанное на рисунке 1.


Рис.1. Результат работы приложения

    Это окно выглядит и функционирует точно так же, как и окно, созданное программой из предыдущего шага, разве только имеет другой заголовок. Существует, правда, и более важное отличие. Теперь основное окно - это окно вашего собственного класса TWndw, а не класса, определенного по умолчанию TFrameWindow. Как следствие, вы можете добавлять в этот класс любые функции, обеспечивающие необходимое поведение основного окна.

    Для замены вашим оконным классом класса, используемого по умолчанию в TApplication, необходимо переопределить функцию InitMainWindow(). Для этого сначала создайте ваш собственный класс приложения, производный от TApplication. В примере этот новый класс выглядит следующим образом:

// Класс приложения.
class TApp : public TApplication
{
  public:
	 TApp() : TApplication() {};
	 void InitMainWindow();
};

    Здесь конструктор ТАрр не содержит строки заголовка, а вместо нее берет для данного аргумента нулевую строку, принимаемую в классе TApplication по умолчанию. Вам не нужна строка заголовка: вы укажете ее при задании основного окна приложения. Заметьте, что конструктор в ТАрр вызывает конструктор TApplication:

    TApp() : TApplication() {};

    Это позволяет базовому классу ТАрр выполнять любую необходимую для программы инициализацию. И наконец (самое главное - причина создания нового класса!), заметьте, что в классе ТАрр мы переопределили функцию InitMainWindow() класса TApplication.

    Таким образом, после объявления нового класса, производного от TApplication, мы получили полноценное приложение, похожее на приложение из предыдущего шага; основная разница в том, что мы создали собственный экземпляр TApplication. К сожалению, этого недостаточно для создания полезной программы. Далее мы должны объявить класс главного окна для нашего приложения:

// Класс основного окна.
class TWndw : public TFrameWindow
{
  public:
	 TWndw(TWindow *parent, const char far *title):
			 TFrameWindow(parent, title) {}
};

    Здесь мы создали класс TWndw основного окна на базе класса TFrameWindow, являющегося общим оконным классом. Конструктор TWndw берет два аргумента - указатель на родительское окно и заголовок окна - и передает их конструктору TFrameWindow. (Сам TFrameWindow является производным по отношению к TWindow.) Помните, что, поскольку мы намеревались использовать класс TFrameWindow, необходимо включить в программу его заголовочный файл FRAMEWIN.H.

    Теперь, объявив собственный оконный класс, нам предстоит использовать его для создания главного окна приложения. Для этого вызывается конструктор класса TWndw, тот самый, который вызывался в функции InitMainWindow() класса ТАрр:

void TApp::InitMainWindow()
{
  //Создает новое главное окно.
  TFrameWindow *wndw = new TWndw(0, "Окно 2");
  //Определяет, какое окно использовать в качестве главного.
  SetMainWindow(wndw);
}

    Оператор new динамически создает объект TWndw, возвращая требуемый указатель типа TWindow. Первый аргумент конструктора TWndw равен нулю, поскольку это окно не имеет окон-родителей. Второй аргумент - заглавие, появляющееся в строке заголовка при создании окна. Если вы передаете окну заголовок при создании объекта приложения (как в примере из предыдущего шага), в окне появляется заголовок, указанный в конструкторе. Вот почему в примере этого шага строится объект приложения без строки заголовка. Зачем его включать, если он не используется?

    MainWindow, указатель на TWindow, входит в состав класса TApplication, являющегося базовым для класса ТАрр (стало быть, ТАрр имеет собственную копию MainWindow). Чтобы задать значение этого указателя, вызывается функция SetMainWindow() объекта прикладной программы, имеющая в качестве единственного аргумента указатель на TFrameWindow или окно, производное от TFrameWindow.


    Замечание. В OWL существует функция SetMainWindaw(), которая избавляет от прямого обращения к MainWindow. Доступ к данным класса через его функции - это в духе объектно-ориентированного программирования, требующего максимального сокрытия данных класса.

    Для создания полноценного окна нужно научить его "отвечать" на сообщения Windows.

    На следующем шаге мы рассмотрим организацию обработки сообщений Windows.




Предыдущий шаг Содержание Следующий шаг