Автор Eric Shepherd

Да. Правильно, мы напишем BeOS приложение "Hello World" :-) Мы создадим приложение, окно и элементы управления и нарисуем текст в окне.

Эта заметка не содержит в себе всех необходимых вам знаний, но в качестве ознакомления вполне стоит прочтения. Не будет лишним, если вы откроете книгу "Be Developer's Guide" или html-книгу BeBook, чтобы обращаться к ним за более детальным объяснением.

Для этого проекта вам понадобится включить следующие заголовочные файлы:

	#include <Application.h>
	#include <Window.h>
	#include <View.h>

Итак, начнем с начала: класс BApplication. В сущности, класс BApplication описывает связь между вашим приложением и частью ядра BeOS под названием Application Server. Application Server управляет системой сообщений, формированием изображения и всякими другими делами, которые необходимы приложениям. Так что, перед тем, как что-либо нарисовать или принять или послать сообщение, вы должны создать объект BApplication.

Обычно, вы делаете это, создавая свой класс, унаследованный от BApplication, так что вы можете изменяя виртуальные методы, изменить поведение вашего приложения. В нашей программе "Hello World", вы создадите для этого класс HelloApp. В функции main() вы создадите объект BApplication (или объект класса, унаследованного от BApplication) и запустите его. Перед тем, как создавать класс HelloApp, давайте посмотрим на функцию main() ,где мы будем его использовать:

	void main(void) {
		HelloApp *theApp;    // Указатель на на наш объект Aplication
		theApp = new(HelloApp);
		theApp->Run();
		delete theApp;
	}

Все, что делает функция main(), это создает объект класса HelloApp, который унаследован от BApplication, и затем вызван метод Run(). Метод Run() - это замкнутый цикл, в котором обрабатываются приходящие в приложение сообщения. Выход из него происходит только после завершения приложения. После того, как метод Run() возвращает управление, мы удаляем наш объект-приложение,

Полезно также помнить, что глобальная переменная be_app всегда указывает на ваш объект BApplication и вы не должны держать где-то указатель на него для вызова методов. Хотя, если вы добавили свои методы к BApllication, тогда перед доступом к ним, вы должны делать явное указание типа. Т.е. ((TestApp*)be_app)->SayURA();

Теперь посмотрим на класс HelloApp:

	class HelloApp : public BApplication {
	public:
		HelloApp();

	private:
		HelloWindow	*theWindow;
	};

Как было сказано выше, HelloApp унаследован от BApplication. Нам только необходимо переопределить конструктор. Одна private (скрытая) переменная, theWindow, используется для хранения указателя на наше окно приложения. Теперь посмотрим на конструктор:

	HelloApp::HelloApp() : BApplication("application/x-vnd.Be-HelloWorld") 
	{
		BRect windowRect;

		windowRect.Set(50,50,200,200);
		theWindow = new HelloWindow(windowRect);
	}

Сначала идет обращение к родительскому конструктору, с передачей строки "application/x-vnd.Be-HelloWorld". Эта странно-выглядящая строка - сигнатура приложения. В ней говорится, что данное приложение-это приложения, и его автор(vendor) Be,Inc. Название приложения - HelloWorld. Это стандартный способ для идентификации приложений, эта строка может также использоваться другими программами для связи с вашим приложением.

Далее, мы создаем объект BRect. BRect это прямоугольник. Он используется для определения прямоугольных областей на экране, содержит переменная для хранения координат и имеет несколько методов для установки и изменения. Один из них - это Set(), который мы используем для установки прямоугольника с точки (50,50) до (200,200) . Он занимает площадь 151 пиксель на 151. Порядок аргументов: лево, верх, право, низ.

Этот BRect мы затем передадим в конструктор HelloWindow. Он будет определять позицию и размеры создаваемого окна. Помните, что мы сохраняем указатель на это окно в нашем HelloApp.

Самое время взглянуть на сам класс HelloWindow:

	class HelloWindow : public BWindow {
	public:
		HelloWindow(BRect frame);
		virtual bool QuitRequested();
	};

Мы имеем конструктор, который принимает объект класса BRect как аргумент, и метод QuitRequested()

	HelloWindow::HelloWindow(BRect frame)
		  : BWindow(frame, "Hello World", B_TITLED_WINDOW,
			B_NOT_RESIZABLE|B_NOT_ZOOMABLE) 
	{
		AddChild(new HelloView(Bounds()));
		Show();
	}

В качестве заголовка окна передается строка "Hello World". B_TITLED_WINDOW - флаг, описывающий тип окна - стандартное окно со строкой вверху, где находятся заголовок и кнопка закрытия окна. B_NOT_RESIZABLE и B_NOT_ZOOMABLE - флаги, уточняющие, что окно не может менять размер и масштабироваться. После создания окна, нам надо добавить в окно представление (view). Окна - это контейнеры для других представлений. Это весьма интересный момент, и очень важно его понять. Окна - контейнеры для представлений. Вы не можете рисовать прямо в окне. В должны вначале создать представление и вставить его в окно. Окно может содержать в себе сколько угодно представлений, а те в свою очередь другие представлений. Мы рассмотрим это подробнее в следующей статье. Сейчас у нас в окне только одно предсталение. В данном случае мы хотим, чтобы представление имело размеры окна и полностью его закрашивало. Для этого мы создаем HelloView, даем ему BRect с размерами, полученными от метода Bounds(). Bounds() - это метод BWindow, который возвращает размеры окна. Эти размеры - площадь, занятая окном, но координаты - локальные внутри окна.

Если у вас стоит разрешение 640x480, то левый верхний угол экрана имеет координаты (0,0), а правый нижний угол имеет координаты (639,479). Это называется экранные координаты. Когда вы создаете окно, вы определяете местоположение вашего окна, используя экранные координаты. Когда окно уже создано, все что вы делает внутри окна, делается в локальных координатах.

Метод Bounds() класса BWindow возвращает размеры окна в локальных координатах. Т.е. в нашем случае это прямоугольник (0,0)-(150,150).

Мы передаем BRect в конструктор HelloView и наш элемент заполняет собой все окно. Указатель на созданный экземпляр HelloView передается в метод BWindow AddChild(). Как мы уже говорили, BWindow - это контейнер представления. Элементы, вставленные в окно, называются дочерними элементами. После того, как элемент вставлено в окно, любое изменение содержимого элемента становится видно в окне.

Затем мы вызываем метод Show(). Этот метод BWindow делает окно видимым. До его вызова окно невидимо.

Другой метод, который мы объявили для класс HelloWindow - это метод QuitRequested(), он вызывается каждый раз, когда кто-то пытается закрыть окно. Вот его код:

	bool HelloWindow::QuitRequested() {
		be_app->PostMessage(B_QUIT_REQUESTED);
		return true;
	}

Все очень просто. Мы просто посылаем приложению сообщение B_QUIT_REQUESTED. По умолчанию, после приема приложением этого сообщения, цикл Run() этого приложения заканчивается. Затем мы возвращаем true, чтобы показать, что мы разрешаем закрыть это окно. Если метод QuitRequested() возвращает false, это означает, что окно не будет закрыто. Это нужно для тех, случаев, когда пользователь пытается закрыть окно с несохранным документом.

В завершении, посмотрим на класс HelloView, который унаследован от BView.

	class HelloView : public BView {
	public:
		HelloView(BRect frame);
		virtual void Draw(BRect updateRect);
	};

	HelloView::HelloView(BRect frame)
		: BView(frame, "HelloView", B_FOLLOW_ALL_SIDES,
			B_WILL_DRAW) {
	}

Как видно, сам конструктор пустой. Мы просто вызываем конструктор родителя (BView) , с передачей ему размеров. Имя элемента "Hello View". Также мы указали флаги B_FOLLOW_ALL_SIDES , который означает, что при изменении размеров родителя, в данном случае окна, наш элемент будет изменять свои размеры соответственно изменению размеров окна, и B_WILL_DRAW, который сообщает Application Server, что наш элемент имеет работающий метод Draw(). Application Server вызывает метод Draw() каждый раз, когда необходимо обновить содержимое окна BRect передается в этот метод для указания региона, нуждающегося в перерисовке.

	void HelloView::Draw(BRect updateRect) {
		MovePenTo(BPoint(20,75));      // Переместим "перо"
		DrawString("Hello, world!");
	}

В данном случае мы игнорируем параметр updateRect.

В следующей статье мы сделаем окно с несколькими дочерними элементами, и начнем обзор основных аспектов пользовательского интерфейса.