Section 3.20 時計の実装(番外編2)

今回は何するの?
今回はウィンドウの見た目を変えようと思うんだ。
ウィンドウの見た目?
今の時計ってこんな感じでしょ。

ウィンドウ枠のある時計

うん。でもそれがどうかしたの?
今回は、見た目をこんなふうにしてみようっていう話。

ウィンドウ枠のない時計

これって、ウィンドウの形を時計の枠の形に合わせるってこと?
そうそう。
デスクトップアクセサリの時計とかって、よくこんな感じになってるでしょ。
そういえばそうだね。
あと、§0.3で目標を立てたときに、こういう時計を作るって言ったしね。
あ〜、そういえばそんなこと言ってたっけ。
というワケで、今回はこういうウィンドウを作ってみるんだけど…
ウィンドウの形を変えると、メニューがつけられなくなっちゃうんだよね。
あ、そっか。
ウィンドウを時計の枠の形に合わせると、メニューを表示するところがなくなっちゃうね。
だから、後でちょっとメニュー関係の仕様を変えることにするね。
うん、りょーかい。
じゃ、まずはウィンドウの形を画像に合わせてみるね。
それってなんか難しそうじゃない?
ううん、そんなことないよ。
画像さえ用意すればあとは簡単。
あ、そうなんだ。
どんな画像を用意すればいいの?
メイン画像とマスク画像って知ってるよね?
うん。
マスク画像って、メイン画像の透明度に対応してて、2つ合わせて1つの画像になるんだよね。
そうそう。
で、まずはこういうマスク画像を用意するの。

<マスク画像>

マスク画像

このマスク画像は、時計の枠の内側を白、外側を黒にした画像なんだ。
ってことは、時計の枠の内側だけが表示されて、外側は透明になるよね。
普通にレイヤに表示する場合はね。
ウィンドウの形を画像に合わせる場合は違うの?
ウィンドウの場合は、表示する部分の色が表示しない部分の色より明るくなるように作るの。
ちなみに、灰色にしても半透明にはならないよ。
へぇ、そうなんだ。
まぁ、普通はわかりやすいように、表示する部分を白、表示しない部分を黒にすればいいと思うよ。
うん、わかった。
あとは、メイン画像とマスク画像をプライマリレイヤに読み込めばいいんだけど、 その前にちょっとやっとかなくちゃいけないことがあるんだ。
何をしなくちゃいけないの?
ClockWindow クラスのコンストラクタで、こんなふうにウィンドウの見た目を変えとくの。

<ウィンドウ外見の変更>

// コンストラクタ
function ClockWindow()
{
    super.Window();

    borderStyle = bsNone;  // ボーダーのないウィンドウにします
    innerSunken = false;   // フラットなウィンドウにします

    // 以下略
}

borderStyle って、§3.15 でウィンドウのサイズを変えられないようにするために使ったプロパティだよね?
うん。あの時は bsSingle に設定したよね。
今回は bsNone になってるね。
これってどういう意味なの?
bsNone は、タイトルバーとか枠がないウィンドウを作る時に指定するんだ。
ちなみに、borderStylebsNone にすると、こんなウィンドウができるよ。

borderStylebsNone のウィンドウ>

borderStyleがbsNoneのウィンドウ

これってウィンドウなの!?
うん、これもちゃんとしたウィンドウだよ。
まぁ、画像の形にウィンドウの形を合わせる時とか、特別な場合にしか使わないけどね。
だよねぇ…こんなウィンドウ見たことないもん。
あと、innerSunken プロパティを false にしとく必要があるんだ。
innerSunken プロパティって?
innerSunken プロパティは、 クライアント領域が凹んだような外見を持つかどうかを表すプロパティだよ。
それってどういうこと?
こういうこと。

innerSunkentrue のウィンドウ(左)と false のウィンドウ(右)>

innerSunkenがtrueとfalseのウィンドウ

左側が innerSunken プロパティが true になってるウィンドウで、 右側が false になってるウィンドウ。
innerSunken プロパティが true になってる方はウィンドウが立体的に見えるけど、 false になってる方は、ウィンドウが平らに見えるね。
うん。
ウィンドウの形を画像に合わせる時は、ウィンドウは平らにしなくちゃいけないんだ。
ふぅん、そうなんだ。
で、ウィンドウの外見を設定したら、次はプライマリレイヤに画像を読み込むんだ。
画像を読み込む時にも何か特別なことするの?
ううん、別に特別なことはしなくていいよ。
このマスク画像を "frame_m.png" っていう名前にしてプロジェクトフォルダに置いてから、 loadImages メソッドを使って、プライマリレイヤに普通に画像を読み込めば OK だよ。

<画像の読み込み>

// コンストラクタ
function ClockWindow()
{
    super.Window();

    borderStyle = bsNone;  // ボーダーのないウィンドウにします
    innerSunken = false;   // フラットなウィンドウにします

    add(new Layer(thisnull));
    primaryLayer.loadImages("frame.png");  // プライマリレイヤに枠の画像を読み込みます
    primaryLayer.setSizeToImageSize();     // プライマリレイヤのサイズを画像サイズに合わせます

    // 以下略
}

loadImages メソッドって、KAG の image タグと同じで、 ファイル名の最後に _m が付いてる画像があったら、マスク画像として読み込まれるんだよね?
ん、そだよ。
で、次に setMaskRegion メソッドを使って、ウィンドウの形を画像の形に合わせるんだ。

<ウィンドウリージョンの設定>

// コンストラクタ
function ClockWindow()
{
    super.Window();

    borderStyle = bsNone;  // ボーダーのないウィンドウにします
    innerSunken = false;   // フラットなウィンドウにします

    add(new Layer(thisnull));
    primaryLayer.loadImages("frame.png");  // プライマリレイヤに枠の画像を読み込みます
    primaryLayer.setSizeToImageSize();     // プライマリレイヤのサイズを画像サイズに合わせます

    setMaskRegion();  // ウィンドウの形を画像の形に合わせます

    // 以下略
}

これでウィンドウの形が画像の形に合わせられるよ。
これだけでいいの?
うん、これだけでいいの。
ホントに簡単だねぇ。
でしょ。
ちなみに、setMaskRegion には引数が1つあるんだけど、 マスク画像の表示しない部分の色を黒にして、表示する部分の色を白にすれば省略できるよ。
今回はマスク画像がそうなってるから引数を省略してるんだね。
そ。引数の意味はここでは説明しないから、詳しく知りたい場合は、吉里吉里2リファレンスの Window クラスの setMaskRegion メソッドの項目を参照してね。
はーい。
ウィンドウの形を画像に合わせると、メニューが表示できなくなっちゃう以外に、 もう1つ問題が起きるんだけど、何だかわかる?
えっ? え〜っと……なんだろ?
タイトルバーがなくなるから、ウィンドウが動かせなくなっちゃうんだ。
あ、そっか。ウィンドウってタイトルバーをドラッグして動かすもんね。
でも、それってまずいんじゃないの?
もちろん、そこはちゃんと考えて作られてるよ。
タイトルバーがない時でも、Window クラスの beginMove っていうメソッドを使えば、ウィンドウを動かせるんだ。
どうやって動かすの?
ウィンドウで onMouseDown イベントが起きた時に、 beginMove メソッドを呼び出せばいいんだ。

<ウィンドウを動かすためのスクリプト>

function action(ev)
{
    switch(ev.target)
    {
    case this:
        if(ev.type == "onMouseDown")
            beginMove(); // ウィンドウの移動を開始します

        // 以下略
    }
}

これで、タイトルバー以外の場所でドラッグしてもウィンドウを動かせるようになるんだ。
へぇ…これも簡単にできるんだね。
でしょ。
じゃあ、実際に実行してみよっか。
うん!
今回必要なスクリプトと画像はこれね。
この6つのファイルをプロジェクトフォルダに置いてから実行してみて。
は〜い!
あっ、その前に!
ん? なに?
今回はメニューを使ってないから、代わりにキーかクリックで操作するようにしてるんだ。
あ、そっか。今回はメニュー作れないんだったよね。
今回の時計の操作法はこうなってるから。

<今回の時計の操作法>

うん、りょーかい。
じゃあ、実行してみるね。
うん。

<実行結果>

表示されたウィンドウ

お〜、ちゃんと時計の画像の部分だけが表示されてる!
時計の部分をドラッグすると動かせるでしょ?
ほんとだ。普通のウィンドウみたいに動かせるね!
あと、キーを使って操作できるかもチェックしてみて。
はーい。
……うん、O, S, C, ESC キーでちゃんと操作できるね。
ん、OK だね。
それじゃ、これで第3章は終わり。
これで§0.3で立てた目標が達成できたね。
うん、そだね。
これからどうするの?
次の章からは、TJS を使って色んなクラスを作って、それを KAG のスクリプトで使っていこうと思うんだ。
あ、そうなんだ。
まぁ、一応 TJS を使って KAG の機能をパワーアップしよう、ってのが本来の目的だからね。
第3章までは、ある意味そのための前置きって感じかな。
え、そうなの? ここまでの長さって、とても前置きっていうレベルとは思えないんだけど…
ん〜、それは確かにそうかもね。
でも、これでもまだ説明できてないことが結構あるんだよ。
これだけ色々やってきたのに?
それだけ TJS は奥が深いってことだね。
ま、でもここまでで基本的なことは身についてると思うから、これから先の応用編もうまくやっていけるはずだよ。
そうなの?
うん。
というワケで、次の章もがんばってついてきてね!
は〜い!


前へ | TOP | 次へ