第3回: ウィンドウを開いてみる

今回は、GUIならまずはじめに、ということで、ウィンドウを開いてみましょう。ウィンドウを正しく動作させるまでには道のりは長いですが、頑張っていきましょう。

今回のプログラム全体を固めたものはこちらです: lecture2.tar.gz

1. 確認

まず、前回(第2回)でやったようにして、下ごしらえをしてください。別に自由に決めてもらってかまわないのですが、今回はlecture2というターゲット名・ディレクトリ名にすることとして話を進めます。

ここまで正しくできているかどうか、以下の手順で確認してください。(pcat/ディレクトリの中にいるとします。)

$ pwd
/usr/local/brightv/appl/lecture2/pcat
$ grep '^TARGET *=' Makefile
TARGET = lecture2

このようになっていればまず大丈夫でしょう。違った結果になった場合は、ここまでの作業を見直してみてください。

2. ソースコード

前回のものから比べると、圧倒的に長くなりましたが、まずソースコードです。頑張って打ち込んでみてください。

#include <basic.h>
#include <bstdio.h>
#include <btron/proctask.h>
#include <btron/hmi.h>

extern "C" W main(W argc, TC* argv[])
{
  TC text[] = {L"Hello, World!"};
  RECT r = {{ 100, 100, 400, 300 }};
  W err, wid, fid;

  fid = dopn_dat(NULL);
  if (fid < 0){
    printf("dopn_dat: %d\n", fid);
    ext_prc(1);
  }

  wid = wopn_wnd(WA_STD, 0, &r, NULL, 2, text, NULL, NULL);
  if (wid < 0){
    printf("wopn_wnd: %d\n", wid);
    ext_prc(1);
  }
  
  slp_tsk(7000);

  err = wcls_wnd(wid, CLR);
  if (err < 0){
    printf("wcls_wnd: %d\n", err);
    ext_prc(1);
  }

  ext_prc(0);
}

2.1. ソースコードを簡略化してみる

まず、

if (〜 < 0){
  printf("〜: %d\n", 〜);
  ext_prc(1);
}

のようになっている部分に注目しましょう。ここに出ているシステムコールに限らず、BTRONシステムコールのほとんどは、返り値が0以下の時にエラーが発生したことを示しています。従って、システムコールから0より小さい値が返った場合にはエラーメッセージをprintfで表示し、ext_prcで直ちに終了するようにしました。実はそれだけの事です。

ならば、ということで、見通しをよくするために、そのエラー処理部分を省略してみましょう。(ここでは練習なのでかまわないとして、実用とするまともなプログラムでは避けましょう。)

#include <basic.h>
#include <bstdio.h>
#include <btron/proctask.h>
#include <btron/hmi.h>

extern "C" W main(W argc, TC* argv[])
{
  TC text[] = {L"Hello, World!"};
  RECT r = {{ 100, 100, 400, 300 }};
  W wid;

  dopn_dat(NULL);
  wid = wopn_wnd(WA_STD, 0, &r, NULL, 2, text, NULL, NULL);

  dly_tsk(7000);

  wcls_wnd(wid, CLR);

  ext_prc(0);
}

だいぶ短くなりましたね。以下ではこの省略版のソースコードをもとに説明します。

3. 説明

3.1. 基本データタイプ

まず、RECTとかWとかについて説明しましょう。

3.1.1. RECT型

RECTは四角形の領域の範囲を表すための構造体です。左上の座標(left, top)・右下(right, bottom)の座標が指定されると、自ずと四角形というのは定まりますが、RECTでもそれらの四つの値を指定します。具体的に、代入する際は、

RECT r;
r.c.left = 100;
r.c.top = 100;
r.c.right = 400;
r.c.bottom = 300;

のようにすれば四角形領域を指定できます。また、このようにするかわりに、

RECT r = {{ 100, 100, 400, 300 }};

と書いて生成時に初期化することもでき、実際プログラムではそのようにしました。

PNT型はここでは説明しませんが、各自調べておいてください。

3.1.2. WとかHとか

BTRONのプログラムを見ているとよく見かけるのですが、WとかHとかがよく出てきます。これらはint, char, ...などの別名です。おすすめは出来ませんが、Wとintは同じものなので、全く同一視して使ってしまって問題ありません。対応は以下の通りです。

これらはよく出てくるので、覚えておきましょう。

3.2. ウィンドウを開いたり、閉じたり

ウィンドウを開くにはwopn_wnd命令を使います。閉じるのにはwcls_wnd命令を使います。

ここでは細かいところについては触れませんが、wopn_wndの主要な引数について説明しましょう。

wid = wopn_wnd(WA_STD, 0, &r, NULL, 2, text, NULL, NULL);

他の引数やwcls_wndの引数については、特別な事をしない限り変更しなくても大丈夫でしょう。詳細は仕様書を見てください。

3.3. slp_tsk

まず、「プロセス」「タスク」という用語から説明します。

超漢字のコンソール上で % ps を実行してみましょう。今動いているプログラムが表示されるはずです。これら一つ一つの「動いている」プログラムを「プロセス」といいます。基本的に、プロセスというものはそれぞれ独立に動いています。"プログラムの起動 = プロセスの生成"という等式が成り立つものだと把握してください。

「タスク」というのはプロセスより細かい実行の流れです。一つのプロセスの中に複数個の流れを持たせたいとき、複数のタスクを作って流れを分岐させます。「マルチタスク」というのは複数のタスクが存在している状況です。

イメージ的には、電球の直列つなぎ・並列つなぎ、あるいは川の流れをイメージするといいでしょう。一つのタスクしかない状況は、直列つなぎに似ていて、順々に+から−方向に電流が流れます。マルチタスクは並列つなぎで、同時に流れていくものだと思ってください。

話がずれましたが、実行しているプログラムは一つのプロセスであると同時に一つのタスクでもあります。cre_tskなどの命令を実行すると、流れを分岐してその時点から並列つなぎにすることが出来るのですが、何もしなければ直列つなぎ、つまりプロセスとタスクが1:1で対応している状況になります。

dly_tskは指定された時間だけ自タスクの実行を遅延(delay)させる命令です。このプログラム中ではプロセスとタスクが1:1で対応していますから、つまりはプログラムを休止させる、ということになります。わかりにくい説明ですが、必ずしも「プログラムを遅延させる」という命令ではないことを把握してもらえるとうれしいです。

ここでは、dly_tsk(7000); としていますが、単位はミリ秒です。従って7000/1000 = 7.0[s]だけプログラムを休止させています。(これがないと、wopn_wndでウィンドウを開いた後、一瞬にしてwcls_wndが行われ、すぐにウィンドウが消滅します。)

3.4. データボックス

BTRON仕様にはデータボックス、という便利なものがあって、データとプログラムを分離できるようになっています。Windowsでいうリソースとかそういうものです。

試しに dopn_dat(NULL); の一行を省いたものを実行してみれば分かりますが、ピクトグラムが表示されなくなります。これは、データボックスを開かないとデータボックスが参照されず、ピクトグラム番号2に対するイメージデータが取り出せないことを意味しています。

dopn_datの引数としてはLINK*型の値を取るようににっているのですが、システムデータボックス(システム標準で与えられるデータボックス)を使うには、NULLを指定すれば良いことになっています。しばらくの間はdopn_dat(NULL);の形で使うものと思っていて良いでしょう。

4. 実行してみる

さて、実行してみましょう。通常なら% run lecture2でOKです。ウィンドウが7秒間の間表示できていれば成功です。

しかし、このウィンドウ、実に困った問題があります。ウィンドウをつかんで動かしたり、閉じたりなどのウィンドウ操作が全く出来ません。なぜでしょうか? この問題の解決は次回以降に譲りますが、ぜひとも少し考えてみてください。

演習問題

  1. wopn_wndに与えている、WA_STDをWA_NORMALに変えてみてください。何が起こるか確かめて、その根拠を仕様書で調べてください。(ヒント: #define WA_NORMAL ...?)
  2. ウィンドウの表示位置・タイトルをそれぞれ変えてみてください。
  3. PNT型について調べてください。
  4. wup_tskという命令について調べてみてください。(理解できなくても大丈夫です。)

[ 戻る ]

Last modified: Sun Oct 3 16:39:16 2010
Valid XHTML 1.0!