画面に描画をしてみよう - 1 / 3 -
前回の連載では、 HelloWorld アプレットを作成することで、 BREW アプリケーションのおおまかな構造について学びました。今回は画面描画の API について詳しく説明するとともに、インタフェイスやアプレット構造体についての理解を深めます。
四角形を描画するアプレット
前回は、アプレット開始時に、携帯電話の画面に "Hello World"と表示しました。今回はまず、前回のおさらいの意味も含めて、青色の背景に赤色の四角形を表示する Square アプレットを作成してみます。
全ソースコードはこのようになります(クリックで別ウィンドウにソースコード表示)。
AEEClsCreateInstance() 関数と、Shape_HandleEvent() 関数の実装は、前回の HelloWorld アプレットと何も変わっていません。今回は Square_OnAppStart() 関数の中で行われている描画処理について完全に理解することを目標にしましょう。
アプレット構造体 AEEApplet
前回はアプレット構造体 AEEApplet の実体について何一つ触れませんでしたので、今回は詳細を調べてみたいと思います。残念ながら、「BREW API リファレンス」には AEEApplet について何も書かれていません。「BREW SDK ユーザーズガイド」にわずかな記述があるだけです。
このような場合は、 BREW SDK のヘッダー ファイルを直接調べてみるのが有効な手段です。 AEEApplet は BREW SDK をインストールしたフォルダの inc\AEEAppGen.h で定義されていますので、このファイルを開いてみましょう。
*Visual C++ 6 では、ソース冒頭にある #include "AEEAppGen.h" の部分を右クリックして現れるメニューから、[ドキュメント "AEEAppGen.h" を開く] を選択することで、即座にファイルを開くことができます。
AEEAppGen.h を調べてみると、次のような宣言があることが分かります。
struct _AEEApplet { DECLARE_VTBL(IApplet) AEECLSID clsID; // アプレットのクラス ID uint32 m_nRefs; // アプレットの参照カウント IShell * m_pIShell; // IShell オブジェクト IModule * m_pIModule; // IModule オブジェクト IDisplay * m_pIDisplay; // IDisplay オブジェクト AEEHANDLER pAppHandleEvent; // アプレットのイベント ハンドラ関数 PFNFREEAPPDATA pFreeAppData; // アプレット解放時に呼び出される関数 }; typedef struct _AEEApplet AEEApplet;
今の段階ではすべてを理解する必要はありません。アプレット構造体は、クラス ID とイベント ハンドラのほかに、いくつかの変数を持つことが分かります。
おそらく、 AEEClsCreateInstance() 関数内で AEEApplet_New() 関数を呼び出すと、これらのメンバ変数が初期化されるのでしょう。
*AEEApplet_New() 関数の実装は AEEAppGen.c で定義されています。特に知る必要はありませんが、余力のある方は覗いてみましょう。
IShell,IModule,IDisplay など、先頭に "I" がつく型は、 "インタフェイス" と呼ばれる構造体です。 BREW プログラミングでは、この "インタフェイス" を理解することが基本となります。
オブジェクトとインタフェース関数
BREW API は、 "オブジェクト" に作用する "インタフェイス関数" として提供されます。難しい言葉が出てきました。 "オブジェクト" とは何でしょうか? "インタフェイス関数" とは何でしょうか?
何も難しくありません。 BREW のオブジェクトとインタフェイス関数について話す前に、 C 言語のライブラリの一般的な設計についてお話します。
例えば、 C 言語で書かれたリンクリストのライブラリを考えてみましょう。そのライブラリは、リンクリストを表す構造体と、その構造体を操作するための関数を提供します。
このようなデータ構造体のことを、 BREW では "オブジェクト" と呼びます。また、データ構造体を操作する関数を "インタフェイス関数" と呼びます。
このように、プログラムをデータ構造体とそれを操作するための関数として整理し、設計することを、「オブジェクト指向プログラミング」といいます。 C++ や Java を習得している方であれば、すでにご存知ですよね。 BREW API は C 言語でオブジェクト指向設計された API なのです。
BREW では、データ構造体とインタフェイス関数をまとめたものを、 "インタフェイス" と呼んでいます。
BREW の "オブジェクト" のことを、 "インタフェイス オブジェクト" と呼んだり、 "インスタンス" あるいは "インタフェイス インスタンス" と呼ぶこともありますが、すべて同じ意味です。
BREW の "オブジェクト" は、 Java や C++ のオブジェクトとほぼ同じであり、 BREW の "インタフェース" は、 Java や C++ のクラスとほぼ同じです。
具体例で説明しましょう。 BREW プログラミングで必ず使用するインタフェイスとして、 "IShell インタフェイス" があります。 IShell オブジェクトとはまさに BREW 実行環境を表現したデータ構造体であり、 IShell インターフェイスは BREW 実行環境を操作するための関数群です。
例えば、 BREW が実行されている携帯電話端末の画面サイズを取得するには、次のようにします。
( AEEDeviceInfo は、携帯電話端末の情報を格納するための構造体です。詳細は「 BREW API リファレンス」を参照してください。)
static void Square_OnAppStart(AEEApplet* app) { IShell* shell; AEEDeviceInfo devinfo; int width, height; // IShell オブジェクトを取得する。 shell = app->m_pIShell; // IShell インターフェイス関数を使用して、画面サイズを取得する。 ISHELL_GetDeviceInfo(shell, &devinfo); width = devinfo.cxScreen; height = devinfo.cyScreen; }
別の例を挙げましょう。 BREW で描画を行うためのインタフェイスとして、 "IDisplay インタフェイス" が用意されています。このインタフェイスは、線を描画したり、四角形を描画したり、描画する色を設定するための関数群を持ちます。
例えば、画面に赤い枠を表示するには、次のようにします。
static void Square_OnAppStart(AEEApplet* app) { IDisplay* disp; AEERect rect; RGBVAL red = MAKE_RGB(255, 0, 0); // IDisplay オブジェクトを取得する。 disp = app->m_pIDisplay; // 赤い四角形の枠を描画する rect.x = 20; rect.y = 20; rect.dx = 40; rect.dy = 30; IDISPLAY_DrawRect(disp, &rect, red, 0, IDF_RECT_FRAME); // 画面ビットマップへの描画を実際に表示する IDISPLAY_Update(disp); }
ここで MAKE_RGB(red, blue, green) は、赤青緑の三原色から色を表す数値(RGBVAL 型)を作成するマクロです。 BREW では色を RGBVAL 型で表現します。
また、 AEERect は長方形を表す構造体で、次のような宣言になっています。
typedef struct { int16 x, y; int16 dx, dy; } AEERect;
BREW のインタフェイスについて理解が深まったでしょうか。インタフェイスといっても特に難しいことはなく、昔から C 言語プログラマーがやってきたことに新しい名前を与えただけなのです。