Be Newsletter

Volume II, Issue 7; February 17, 1998


DEVELOPERS' WORKSHOP: BeOSプログラミングの基礎: Part 1

By Eric Sheppherd

「Developers' Workshop」は、開発者から寄せられる質問に対する解答を提供する、新しい週次の特集です。 毎週、Be社の技術サポートや文書化担当者が実際の開発者から寄せられた質問の中から一つ(あるいは二つ)を選び、答えを提供します。

我々は、新しいセクションを我々のウェブ・サイトに設けました。 下記ウェブ・サイトを訪問して、あなたの考えるニュースレターの話題を送って下さい: http://www.be.com/developers/suggestion_box.html.

 

インテル向けBeOSのリリースが近づくにつれ、全くの新たなBeOSプログラマーが未知の領域に入るべく準備を進めています。 彼らがBeOSアプリケーションを書くことを助けるために(そして、PowerPCプログラマーがBeOSを始めることを助けるために)、私のBe Newsletterの記事では、今後の数回にわたって、BeOSプログラミングの簡単な紹介を行います。

今週は、きわめて基礎的なアプリケーションを作ります。 あなたは「Hello, World?」と言えますか。 この記事と我々の作るサンプル・アプリケーションで、これをどうやって実現するのかを説明します。

ええ、その通りです。我々はBeOSアプリケーションとして「Hello World」を書くことになります。 我々は、アプリケーション、ウィンドウならびにビュー・オブジェクトを生成して、テキストをビューの中に描画します。 この記事では、あなたが知っておくべきことをすべて説明する訳ではありませんが、あなたが実験をはじめられるように、少なくともあなたを目覚めさせ、最初のアプリケーション開発を進められるようにすることが必要になります。 実際、この記事を読み進める上で、あなたはBe Developer's Guideやオンライン版Be Bookを手もとに置いておくべきです。

このプロジェクトのために、以下のヘッダ・ファイルをソース・コードにインクルードしておく必要があります:

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

それでは最初から始めましょう: BApplicationクラス。 このクラスは、BeOSアプリケーションを定義します。 本質的に、BApplicationクラスは、あなたのアプリケーションとアプリケーション・サーバーのリンクを表現します。 アプリケーション・サーバーは、大部分のアプリケーションが扱う必要があるメッセージング、イメージング、あるいは他のよい材料を取り扱います。 それで、あなたがスクリーン上に描画をしたり、メッセージを受けたり送ったりすることを可能にする上で、あなたはBApplicationオブジェクトを生成しなければなりません。

典型的なやり方としては、BApplicationから派生したあなた自身のクラスを生成することによってこれを実現します。したがって、あなたは特定のメソッドを拡張したりオーバーライドすることにより、アプリケーションの動作をカスタマイズすることができます。 Hello Worldプログラムの中で、我々はこの目的を果たすHelloAppという名前のクラスを生成することにします。

アプリケーションのmain()関数の主要な義務は、BApplication(あるいはBApplicationから派生したクラスのオブジェクト)を生成し、呼び出すことです。 我々がHelloAppを生成する前に、典型的なmain()関数(実際に、これは我々のHello Worldプログラムが使うmain()です)を見てみましょう:

void main(void) {
  HelloApp *theApp;    // 我々のアプリケーション・オブジェクトに対するポインター
  theApp = new(HelloApp);
  theApp->Run();
  delete theApp;
}

ここでmain()が行うすべてのことは、すぐ後にあるように、BApplicationから派生する新しいHelloAppオブジェクトを生成することです。 いったんこれ[HelloAppインスタンスの生成]がなされると、アプリケーションのRun()メソッドが呼び出されます。 Run()メソッドは、アプリケーションのイベント・ループです。 これ[Run()メソッド]は、アプリケーションが終了されるまで実行環境に制御を返しません。

いったんRun()メソッドが実行環境に制御を返すと、我々のプログラムは終了しようとしますから、我々はアプリケーション・オブジェクトを削除します。従って、我々はもうオブジェクトを必要としません。

グローバル変数be_appは、常にあなたのアプリケーションのBApplicationオブジェクトを指すことを覚えておくとよいでしょう。 これが意味することは、必要が無ければアプリケーション・オブジェクトへのポインターを保持し続けておく必要が無いということです。ただし、あなたがオブジェクトに独自に実装したメソッドを呼び出す場合は、あなたのクラスに対してbe_appをキャストする必要があります。

それではHelloAppクラスを見てみましょう:

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

  private:
    HelloWindow    *theWindow;
};

先ほど述べた通り、HelloAppはBApplicationから派生しています。 我々はただ我々がする必要があることをされるためにコンストラクタを必要とするだけですので、それは我々が定義するただpublicメソッドだけを持ちます。 単一のプライベート変数であるtheWindowが、我々のアプリケーションのウィンドウへのポインターを保持するために使われます。

HelloAppコンストラクタを調べてみましょう:

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

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

HelloAppコンストラクタは、文字列「application/x-vnd.Be-HelloWorld」を渡して、BApplicationコンストラクタに従います。 この奇妙な外見の文字列は、アプリケーションのシグネチャです。 これにより、このアプリケーションがアプリケーションであり、ベンダがBe社であることが指定されます。 アプリケーションの名前は、「HelloWorld」です。 これは、我々がアプリケーションを識別する際の標準的な手段です; 他のプログラムは、この文字列を使って、あなたのアプリケーションを捜し出し、それにメッセージを渡すことができます。

オブジェクトが構築されたら、次にBRectを生成します。 BRectは矩形オブジェクトです(Be Developer's GuideのInterface Kitの章に詳しい記述があります)。 これはスクリーン上で矩形の上端、左端、右端、そして下端を与えることによって矩形エリアを定義するために使われ、矩形の位置やサイズを指定したり、検索したりするためのいくつかのメソッドを持ちます。

これらのメソッドの一つがSet()であり、我々は矩形が(50,50)から(200,200)の領域を占有するように指定するのに使います。 これによって、150ピクセル幅で、高さも150ピクセルである矩形が指定されます。 Set()に対する引数は、次の順序になります:左、上、右、下[底]の順です。

そのBRectオブジェクトは、我々がウィンドウ・オブジェクトを生成する際に、HelloWindowコンストラクタに渡されます; この矩形は、ウィンドウの生成時に、これをスクリーン上に配置し、サイズを決定するために使われます。 我々がHelloAppのtheWindowフィールドにウィンドウ・ポインターを保存する点に注意して下さい。 ここまでの議論で、HelloWindowクラスに目を通す必要が生じてきました:

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

HelloWindowクラスはコンストラクタを一つ持ち、これはBRectオブジェクトを一つの引数(前の方で検討したように)として受け取ります。また、QuitRequested()メソッドを受け取ります。 HelloWindowは、全てのウィンドウがBeOS上のあらゆるウィンドウの派生元となるBWindowから派生する点に注意して下さい。

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

上に示したコンストラクタは、ウィンドウをセットアップするために、BWindowコンストラクタに従います。 フレーム矩形は、コンストラクタに対する引数として指定され、コンストラクタに渡されます。また、ウィンドウの名前は文字列「Hello World」によって指定されます。 B_TITLED_WINDOWは、生成するウィンドウの種類を示すフラグです: 上部にタブを持ち、その中にタイトルとクローズ・ボックスが描画される、標準ウィンドウを示しています。

B_NOT_RESIZABLEB_NOT_ZOOMABLEは、ウィンドウを閉じたり(ズーム・ボックスも持っていないでしょう)、大きさを変更したりできないことを示すフラグです。

ウィンドウが造られたら、次に我々はビューをウィンドウに付け加える必要があります。 ビューは、他のビューを格納します。 これは面白い概念であり、理解しておくべき重要な概念の一つです。 ウィンドウは、ビューを格納します。 あなたは、ウィンドウ内に直接描画することはできません。 あなたは、まずビューを生成して、それをウィンドウに付与する必要があります。

一つのウィンドウに対して、必要なだけの数のビューを付着することができ、各ビューはさらにサブ・ビューを持つことができます。 我々は、次回の記事でこれをさらに探求します。 今のところ、我々のアプリケーションのウィンドウは、一つのビューを持ちます。

我々の例では、ビューのサイズをウィンドウのサイズとぴったり同じにし、完全にウィンドウを覆うようにします。 したがって、我々がHelloView(これについては、まもなく検討します)を実体化する場合、我々はBounds()メソッドによって得たBRectを渡します。 Bounds()は、BWindowクラスのメソッドであり、ウィンドウの「境界矩形[値]」を返します。

境界矩形[値]は、あるウィンドウによって占有された領域を示しますが、そのウィンドウに対するローカル座標で表されます。 これは、把握しておくべきもう一つの重要な概念です。

あなたのコンピュータが640x480[ピクセル]のスクリーンを持つとすると、スクリーンの上左端の座標は(0,0)となり、スクリーンの下右端は(640,480)となります。 これらは「スクリーン座標系」と呼ばれます。 あなたがウィンドウを生成する場合、あなたはスクリーン座標系を使って、スクリーン上でのウィンドウの位置を指定します。

いったんウィンドウが生成されたら、あなたがそのウィンドウ内で何をしても、それは「ローカル座標系」上でなされます スクリーン座標系がスクリーンの上左端を(0,0)とするように、ローカル座標系ではウィンドウの上左端を(0,0)とします。

BWindowクラスのBounds()メソッドはローカル座標系でウィンドウの矩形を返すので、我々のプログラムの場合、この矩形は(0,0)-(150,150)となり、これはまさに我々のほしい値です。

我々はこのBRectをHelloViewコンストラクタに渡すので、ビューはウィンドウ全体を覆います。 我々は、次にHelloViewクラスを研究します。

newにより戻り値を受け取ったHelloViewポインターは、次いでBWindowのAddChild()メソッドに渡されます。 我々がすでに学んだように、ウィンドウはビューを含みます。 あるウィンドウが含むビューは「子[ビュー]」と呼ばれます。 AddChild()メソッドは、次に、ビューをウィンドウに付け加え、これによってそのビューをウィンドウの子にします。 いったんビューがウィンドウに付け加えられると、ビューの内部でなされるいかなる描画もウィンドウ内で可視状態になります(これは子ビューも親ウィンドウも可視状態にあることを仮定していますが、これについては別の機会に説明します)。

いったん子ビューがウィンドウに付け加えられたら、我々はShow()を呼び出します。 このBWindowのメソッドはウィンドウを可視状態にします--あらゆるBWindowsは、あなたがこのメソッドを呼び出すまで隠されています。

我々がHelloWindowクラスのために定義するもう一つのメソッドがQuitRequested()であり、これは誰かが我々のウィンドウを閉じようとするときはいつでも呼ばれます。 これは、例えばユーザがクローズ・ボックスをクリックした場合に起こります。 コードは、このようになります:

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

これは、非常に単純です。 我々は、単にアプリケーションに対してB_QUIT_REQUESTEDメッセージを投げるだけです。 デフォルトでは、BApplicationオブジェクトがこのメッセージを受けとると、Run()メソッドは単純に終了します(次いで、我々のmain()関数に制御を返し、アプリケーション・オブジェクトを削除して、終了します)。

次に、我々はウィンドウを閉じる許可を与えるために、trueを返します。 QuitRequested()がfalseを返す場合には、これは呼び出し側に如何なる理由であっても、彼らがウィンドウを閉じてはいけないことを示します。 これの明白な適用としては、ユーザに彼らが作業結果をまだ保存していないことを思い出させるための、たとえどんな操作がウィンドウを閉じようとしていても、彼らがキャンセル出来るオプションのあるアラートを示すことが考えられます。

最後に、BViewから派生しているHelloViewクラスを見てみましょう。 ビューは、全ての描画がされる背景です。

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

我々のHelloViewクラスはコンストラクタを持っており、これはビューがその親の範囲内で占めるべきサイズと位置を示すBRectを受け取り、アプリケーション・サーバーがビューの内容をアップデートする場合に呼び出すDraw()メソッドを受け取ります。

コンストラクタは、このようになります:

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

ご覧の通り、我々はコンストラクタの中で何もしません: 我々は単にフレーム矩形を渡すだけで、BViewコンストラクタに従います。 ビューの名前は、「HelloView」です。 我々は、リサイジングモード用にB_FOLLOW_ALL_SIDESフラグを指定し、たとえウィンドウが動かされたり、サイズを変更されたりしても、ビューが常にウィンドウ全体を覆うようにします。また、B_WILL_DRAWフラグを指定し、これは我々がアップデートの際に呼び出す必要のあるDraw()メソッドを実装していることを、アプリケーション・サーバーに伝えます。

アプリケーション・サーバーは、ウィンドウの内容がアップデートされる必要があるときはいつでも、Draw()を呼びます。 これ[アップデート・イベント]は、別のウィンドウが我々の前を通過したり、ウィンドウが最初に表示される場合に起こります。 書き直す必要があるビューの領域を示すBRectがメソッドに渡されます。

void HelloView::Draw(BRect updateRect) {
  MovePenTo(BPoint(20,75));      // ペンを移動
  DrawString("Hello, world!");
}

お分かりのように、Hello Worldでは、我々はupdateRectを無視しています。 我々はBPointオブジェクト(これはスクリーン上の点を表します)をその座標系で生成することによって、ペンを座標(20,75)に置き、それからMovePenTo()メソッドにそのポイントを渡します。

いったんペンが所定の場所に置かれたら、我々はDrawString()を呼び出して、ビューへ「Hello, World!」というメッセージを書き込みます。

私の記事のためのサンプル・コードは、Be社のFTPサイトの以下の場所に置かれる予定です: ftp://ftp.be.com/pub/samples/preview/intro/helloworld_article.zip

次回は、あなたが一つのウィンドウ中で複数のビューをどのように使うことができるかを研究し、いくらかの基礎的なユーザー・インタフェース機能の研究を始めます。 差し当たってはBe Developer's Guideや、Application.hWindow.hおよびView.hといったヘッダ・ファイルを眺め、自分自身で探求を行ってみて下さい。


Copyright ©1997 Be, Inc. Be is a registered trademark, and BeOS, BeBox, BeWare, GeekPort, the Be logo and the BeOS logo are trademarks of Be, Inc. All other trademarks mentioned are the property of their respective owners. Comments about this site? Please write us at webmaster@be.com.