前回の記事では、AIRのウィンドウAPIを用いたサンプルアプリケーションのキャプチャ画像とソースコードを掲載した。今回はその詳細な解説を行いながら、AIRが持つウィンドウ操作用APIについて理解を深めたいと思う。

前回提示したサンプルのポイントを解説していくことにしよう。

(1) 作成したウィンドウは、以下の変数に格納される。

[Bindable]
private var win:NativeWindow;

変数の型はflash.display.NativeWindowだ。NativeWindow APIについては(2)で詳しく解説する。Bindableというタグが付いていることにより、以下のように「ウィンドウ作成」ボタンのenabled属性と連動する。これにより、ウィンドウが表示されている間はボタンを利用することができず、ウィンドウを複数作成することができないようにしている。

<mx:Button x="31" y="36" label="ウィンドウ作成" click="createWindow();" enabled="{win == null}"/>

このテクニックはAIRに限ったものではなく、Flex/ActionScriptプログラミング自体にかかわることなので、詳細は説明しない。

(2) 作成するウィンドウの初期設定を行うには、flash.display.NativeWindowInitOptionsクラスのインスタンスを作成し、属性に値をセットした後、NativeWindowクラスのコンストラクタに渡す必要がある。それを行っているのが以下の部分だ。

// (2) ウィンドウの初期設定を行い、ウィンドウの生成
var initOptions:NativeWindowInitOptions = new NativeWindowInitOptions();
initOptions.systemChrome = NativeWindowSystemChrome.STANDARD;
initOptions.transparent = false;
initOptions.type = NativeWindowType.NORMAL;
win = new NativeWindow(false, initOptions);

NativeWindowのコンストラクタは、第一引数に「即時ウィンドウの表示を行うかどうか」、第二引数に「ウィンドウの初期設定を指定したflash.display.NativeWindowInitOptionsクラスのインスタンス」を渡すことができる。今回は、ウィンドウを表示する前に様々なイベントハンドラの登録などを行っておきたいので、第一引数をfalseとしている。

では、ウィンドウの初期設定情報であるNativeWindowInitOptionsクラスの属性を以下に詳しく説明する。

  • systemChrome属性 - クローム(Chrome)というのは、Windowsのタイトルバーに代表されるウィンドウの枠のことである。指定する値はflash.display.NativeWindowSystemChromeクラスの定数だ。STANDARD(OSネイティブのクロームを使用)、NONE(クロームなし)、ALTERNATE(代替クローム、β版では使用不可)を指定することができる。

  • transparent属性 - ウィンドウの背景を透明にするか否かをBooleanで指定する。この属性をtrueに指定して背景を透明にするためには、systemChromeNONEに指定しておく必要がある。

  • type属性 - 作成するウィンドウのタイプを指定する。指定する値はflash.display.NativeWindowTypeクラスの定数だ。NORMAL(最小化/最大化/閉じるボタンを持つフルセットのクローム、タスクバーへも表示される)、UTILITY(フローティングウィンドウでできたツールパレットのように、「閉じる」ボタンなどしかなく、タスクバーにも表示されない)、LIGHTWEIGHT(systemChromeNONEに指定したときのみ利用できる。タスクバーに表示されない)、MODAL(最前面に出現して、ウィンドウのフォーカスを独占する。β版では使用不可)を指定できる。

type属性については、以下の画像がわかりやすいだろう。

NORMALは、通常のタイトルバーが表示される。

UTILITYは、上のようなタイトルバーが表示され、タスクバーにも表示されない。

LIGHTWEIGHTは、systemChrome=NONEの場合と同じに見えるが、Windowsのタスクバーにタイトルが表示されない。

読者の方々には、この部分のコードをいろいろ修正して、生成されるウィンドウがいかに変化するかを試してみていただきたい。

(3) ウィンドウをフルスクリーン表示にするには、NativeWindowクラスのstageプロパティ(flash.display.Stageへの参照。ウィンドウ内の表示可能領域を表す)を参照し、displayStateプロパティに値を設定する。

win.stage.displayState = StageDisplayState.FULL_SCREEN;

(4) ウィンドウのイベントを検知して処理を実行するには、addEventListenerメソッドを用いる。以下のコードを見てほしい。

// ウィンドウが閉じられた際、変数winにnullを代入
win.addEventListener(Event.CLOSE, function(event:Event):void {
    win = null;
});
// ウィンドウ上でキーを押された場合、ESCAPEキーだったらウィンドウを閉じる
win.stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent):void {
    if (e.keyCode == 27) {
        win.close();
    }
});

ウィンドウ自体に関するイベントはNativeWindow.addEventListenerを、ウィンドウの表示領域内におけるキーやマウス、フルスクリーン化などのイベントはNativeWindow.stage.addEventListenerを用いて、イベントに対してリスナを登録する。

(5) ウィンドウを閉じる、デスクトップ前面に表示する、移動やリサイズを行う、などウィンドウ自体を操作するには、NativeWindowクラスのメソッドを使用すれば良い。(4)においてもNativeWindow.close()メソッドを用いてウィンドウを閉じているし、以下のようにすればマウスドラッグに応じてウィンドウを移動させることができる。 こうした、ウィンドウを操作するメソッドは全て非同期で実行される。実行結果に応じて処理を行いたい場合は、やはりaddEventListenerメソッドを用いて、非同期処理の結果をイベントとして受け取る必要がある。

win.stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void {
    // (5) ウィンドウを移動
    win.startMove();
});

このように、MOUSE_DOWNイベントの結果としてNativeWindow.startMove()メソッドを呼び出すと、AIRランタイムが自動的に「マウスドラッグ→ウィンドウの移動、マウスアップ→移動終了」と言う処理を肩代わりしてくれる。

(6)(7)(8) このサンプルはお遊び的な要素として、アプリケーションの終了時にメインウィンドウがフェードアウトする、という処理を入れている。ウィンドウの透明度を簡単に変更できる、AIRならではのウィンドウエフェクトだ。以下のコードを見てほしい。

// (6) メインウィンドウが閉じようとしている時のイベント処理。
//     mx:WindowedApplicationのclosing属性で指定されている。
private function onClosing(event:Event):void {
    // (7) デフォルトのイベント処理(ウィンドウが閉じる)を中断
    event.preventDefault();
    var mainWindow:WindowedApplication = this;
    // 0.1秒ごとにalpha値をマイナスしていき、0になったらアプリ終了
    var timerId:uint = setInterval(function():void {
        if ((mainWindow.alpha -= .2) <= 0) {
            clearInterval(timerId);
            // (8) アプリ終了
            Shell.shell.exit(0);
        }
    }, 100);
}

いくつもポイントがあるが、コメントに記述されている通りだ。 ( 6)では、このMXMLファイルのルート要素であるmx:WindowedApplicationclosing属性にて、以下のように指定されているため、ウィンドウが閉じる直前ににonClosingメソッドが呼び出される。

<mx:WindowedApplication closing="onClosing(event);" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

(7)は、flash.events.Eventクラスが持つpreventDefaultメソッドを呼び出し、「イベントが起こった時のデフォルト処理」を行わないようにしている。ここでは、「ウィンドウが閉じる」という動作が行われなくなる。ウィンドウを閉じ、アプリケーションを終了するのはフェードアウトが完了した後だ。

(8)は、フェードアウトが終わった際のアプリケーション終了処理だ。flash.system.Shellクラスのインスタンスは常にこのように、Shell.shellとして参照する(シングルトンパターンだ)。Shellクラスは、AIRアプリケーションがOSとの対話を行えるように用意されているクラス。β版では、アプリケーションの終了や、各種のイベントリスナを登録できるようになっている。

以上で、サンプルについての解説は終わりである。ブラウザの枠にとらわれずに、矩形にこだわる必要もなくウィンドウを作成でき、簡単に操作できることがお解りだろうか。

次回からはファイル操作用APIの解説に入る予定だ。