プログラム講座 初級編2

- PICTファイルビューアー -

 初級編2ですが、今度は目の保養(?)にPICT画像をウィンドウに表示する「PICT画像ビューアー」を作ってみましょう。ここではPICTファイルの表示処理についての説明が主な目的です。また初級編1のファイルの扱いはすでに習得しているものとして話を進めます。もし、読んでいない場合は、先に初級編1を読んで下さい。



◆ウィンドウの作成と、表示について
 まず画像を表示するための「ウィンドウ」を表示させます。「ウィンドウ」には下記のようにいくつか種類があります。カッコ内はFuture BASICで指定するウィンドウ指定のパラメーターです。後でウィンドウを表示する種類を決めるときに使います。

 (1)ドキュメントウィンドウ(_doc)
 (2)枠付きダイアログ(_dialogFrame)
 (3)ノーマルダイアログ(_dialogPlain)
 (4)影付きダイアログ(_dialogShadow)
 (5)モーダルウィンドウ(_docNoGrow)
 (6)移動可能ダイアログ(_dialogMovable)
 (7)ズームボックス付きウィンドウ(_docZoom)
 (8)角丸ウィンドウ(_docRound)
 (9)フローティングパレット(WDEFBASEID_noGoAway)
(10)クローズボックス付きフローティングパレット(WDEFbaseID)
(11)横向きフローティングパレット(WDEFbaseID_SideDrag)
(12)ズーム付きフローティングパレット(WDEFbaseID_hasZoom)

 簡単にそれぞれのウィンドウの使い方(使い道)を説明しておきます。
(1)と(7)のウィンドウは割と使われるタイプの物です。違いはズームボックス(右上の□)があるかないかだけです。文書の表示や画像の表示など多くのことに使用されます。

(2)のダイアログは、プレファレンスやアラート(警告表示)などに使用します。ユーザーに注意を促したり、設定を行ってもらうためなどに使用します。

(3)(4)は、今はあまり使用されません。昔はアバウト画面などに使用されていました。今でも使用するものもありますが、ここらへんは好みに応じてどうぞ、といった所です。一枚絵の場合は影付きダイアログで表示させると結構見栄えが良いかもしれません。

(5)のモーダルウィンドウも結構使用されます。フローティングパレットの替わりにフローティングウィンドウとして使われることがあります。各種ツールの選択などのアイコンをこのウィンドウに表示させておくといった使い方をします。その他サイズ変更して欲しくない場合などに使います。

(6)移動可能ダイアログはシステム7以降でのみ使用できます。Future BASICはシステム6でも使用できますので、もしシステム6で使用する場合はこのダイアログは使用できないという事を念頭に入れておきましょう。このダイアログは待ち時間を表す場合に使用されます。ちなみにWindows 95ではダイアログは全てこの移動可能ダイアログになっています。

(8)は今はほとんど使われません。標準で付いてくる電卓やパズル程度です。このウィンドウは、それ単体で簡潔するような場合に使用します。

(9)〜(12)のフローティングパレットはハイパーカード登場以降使用されるようになりました。画面の狭いMacにとっては結構重宝します。フローティングパレットは基本的にアイコンメニューや設定などを行うような使い方をします。ツールパレットという呼び方の方が適切かもしれません。また、これらのフローティングウィンドウはFuture BASIC II以降は標準対応していますが、それ以前のバージョンでは標準では対応していませんので注意が必要です。

 さて、やっと本題に入りましょう。Future BASICでは「自動的に一枚ウィンドウを作成し表示」します。前回の初級編ではウィンドウの設定も何もしれないのに、勝手にウィンドウが表示され、その中にテキストが表示されたのは、このためです。ちなみに、このウィンドウを表示させたくない場合は「WINDOW OFF」という一文を入れれば表示されなくなります(作成もされません)。
 今回はウィンドウ内に画像を表示しますので、とりあえずモーダルウィンドウを使って表示させてみましょう。ウィンドウを作成、表示させるには以下の命令を使用します。

WINDOW 番号,名称,座標,形状,属性,クラス

 いくつかパラメータがありますが、今回は「番号」「名称」「座標」「形状」のみ使用します。
 「番号」はウィンドウの「管理番号」の事です。先頭に#記号を付けてわかりやすくしておくのがいいでしょう。この管理番号にマイナスの数も指定する事ができます。この場合は、そのウィンドウが表示されなくなるだけです。マイナス番号のついたウィンドウが生成されるわけではありませんので注意してください。またFuture BASIC IIでは1〜255まで使用できますが、それ以前のバージョンでは1〜63までしか扱えませんので注意が必要です。今回は1枚しか使わないので「ウィンドウ番号は1」にしてあります。

 「名称」というのはタイトルバーに表示される名前の事です。"ABC"といった具合に指定します。A$といった変数も使えます。が、変数同志の加算などを行うとエラーになってしまう場合があります。

 「座標」はウィンドウの表示位置またはウィンドウのサイズです。Future BASIC IIでは自動センタリング機能などもあります。今回は絶対座標で指定するようにしました。座標を指定するには、

(20,30)-(130,450)

 といった具合に指定します。今回は使っていませんが変数でも指定する事ができます。この場合は「レクタングル」(矩形範囲)を指定します。これに関しては後述します。

 「形状」は先ほど説明したウィンドウの形状を指定します。

 「属性」は「形状」で指定したウィンドウにさらにいろいろなものを追加削除したい場合に使用します。今回は使用する必要がありません。もし、必要があるとしたらクローズボックス(左上の□)を取り除く指定、_NoGoAwayくらいでしょうか。

 「クラス」というのは使ったことがないので不明です(^^; マニュアルを見て下さい。



◆キー入力とボタンクリックを待つ
 面倒なpictファイルの読み込みは最後にして、まずはキーの入力とボタンが押されるまで待つという部分について説明します。
 キーの入力はイベント云々とやらなくてもINKEY$という命令を使えば簡単に調べる事ができます。この命令は入力された文字を返します。今回はキー入力があったらプログラムを終了するようにしてあります。

 次にマウスのボタンの入力を調べるには「ツールボックス」を呼び出します。実は簡単にクリックを調べるプログラム(ツールボックスコール)が用意されています。「FN BUTTON」とすればボタンが押されたときはtrue、押されていない時はfalseを返します。ですから、この入力状態を調べて押されていなければ(false)待つという具合になります。

 キーの入力を待つ、ボタンの入力を待つという場合は、初級編1でも出てきた「WHILE〜WEND」命令が便利です。例えば何かキーが押されるまで待つには、

WHILE INKEY$="":WEND

で終わってしまいます。ボタンも同様に、

WHILE FN BUTTON = false:WEND

でボタンが押されるまで待つという処理ができます。
 最後に一番重要なpictファイルの読み込みと表示を解説します。

◆PICTファイル(画像)の読み込みと表示
 このPICTファイルの読み込みに関してはFuture BASIC購入時についてくるサンプルプログラムにすでに用意されています。他にも有益なサンプルプログラムがあります。マニュアルにも多々ありますので有効に利用すべきです。使えるなと思ったものは、チェックするか調べるようにしましょう。大抵の場合、サンプルが用意されています。ここがFuture BASICのいい所でもあります。

 それでは、ゆっくり説明します。まず最初のDIM rect.8というのは、8バイト(英数字1文字で1バイト:1バイトは0〜255までの値)の領域を用意するものです。これは何に使うかというとPICT画像の表示する大きさを格納するために必要なのです。

 f$ = FILES$(_fOpen,"PICT",,vRefNum%)は初級編1でやったファイルダイアログを表示してPICT画像を選択させるものです。今回はPICT画像だけなのでファイルタイプは「PICT」になっています。このファイルタイプは大文字小文字を区別しますので間違えないようにしましょう。
 何もファイルが選択されなかった場合はf$は「からっぽ」になります。そのまま処理してしまってはエラーになってしまいますので、ファイルが選択された場合のみ処理を続行するようにします。

 OPEN "I",#1, f$,,vRefNum%も初級編1でやったように指定されたファイルを読み込み専用でオープンします。

 fileSize& = LOF(1,1)というのは新しく覚える命令です。ここでPICTファイルの大きさを変数fileSize&に入れています。変数の最後に&マークが付くと「32ビット整数」まで扱える変数になります。
 LOFはファイルサイズを求める関数です。LOF(ファイル番号,レコード長)のように指定します。レコード長は1にしておいてください。でないと正確なサイズを求めることが出来ません。ここではファイル番号は1になっていますのでLOF(1,1)になります。

 pictHandle& = FN NEWHANDLE(fileSize&+4)も新しく覚える命令です。ここでPICT画像を格納するための「ハンドル」を用意しています。ハンドルについては、今回は詳しく触れません。FN HEWHANDLE(fileSize&+4)は、指定された大きさの領域を確保します。ここではPICT画像より4バイト大きいハンドルを用意しています。
 もし、ここでメモリ不足だった場合は、FN HEWHANDLE関数(ツールボックスコール)は0を返します。つまり確保できたかできなかったかは0かどうかを調べればよい事になります。

 err = FN HLOCK(pictHandle&)はハンドルをロックする命令です。今回は詳しく触れませんが、メモリ内容を操作する場合は、必ずこの関数を呼び出す必要があります。忘れると、たまにうまくいかないという頭を悩ます現象が起きます。
 もしロックできない場合(まず、ハンドルが確保されている場合は大丈夫)はエラーコードを返します。エラーコードはリファレンスマニュアルの最後の方に載っていますので、もしエラーが発生したら、そのエラーコードを元に原因を探るといいでしょう。エラーがなければ返り値は0になります。

 READ FILE#1, [pictHandle&], fileSize&は指定されたファイル番号のファイルから指定サイズ分だけ一度にメモリに読み込んでしまう命令です。初級編1でやったINPUT #1,a$をいっきに処理してしまうものだと思ってもいいでしょう。ここでPICTファイルを読み込んでいます(データ全部を読み込みます。リソースは読み込みません)。

 BLOCKMOVE [pictHandle&]+512,[pictHandle&],fileSize& - 512は詳しく触れませんが、PICTファイルの構造と関係がありPICTファイルは先頭512バイトは基本的に使用されません。ここでは、その不要な部分を削除(実際は移動させている)しているのです。これについては、別の機会に解説したいと思います。ちなみに多用する命令ではありません。

 err = FN HUNLOCK(pictHandle&)はFN HLOCK命令の逆の動作をしハンドルのロックを解除します。

 err = FN SETHANDLESIZE(pictHandle&, fileSize&-512)もツールボックスコールです。ここで先ほど削除した512バイト分メモリを解放しています。別になくても構いません。昔は今と違ってメモリは貴重でしたので、ちょっとしたメモリも無駄にはしなかったわけです。

ptr& = [pictHandle&]
pictLY% = PEEK WORD(ptr& + 6)
pictLX% = PEEK WORD(ptr& + 8)

 この3行でPICT画像の大きさを求めています。本当は+6とか+8とか書かずに_pictx云々と書かなければいけないのですが、早々PICTファイルフォーマットが変更される事はないので、このようにしています。ファイルフォーマットを知っていないとできないのですが(^^; とりあえず、このようにすればOKです。PEEK関数については、初級編(別のプログラム解説において)にて説明します。

 ここまでくれば後はウィンドウにPICT画像を表示するだけです。
CLSはウィンドウを背景色で消去する命令です。

 まず表示する画像の大きさを設定しておく必要があります。この大きさを設定するのがCALL SETRECTという命令です。一番最初に設定したDIM rect.8の変数rectは、ここで使用します。このrect変数に任意のサイズを指定し格納させる命令がSETRECTというわけです。今回は原寸大で表示させるので、先ほど求めたPICT画像のサイズをそのまま指定しています。

 実際にPICT画像を描画させるにはDRAWPICTURE命令を使用します(ツールボックスコール)。PICT画像ハンドルと表示サイズを指定してやればOKです。これでウィンドウにPICT画像が表示されます。

 err = FN DISPOSHANDLE(pictHandle&)は使い終わったハンドルを削除するものです。今回はただ表示するだけですので、さっさと破棄しています。アプリケーション中で使い続ける場合は、このような場所では破棄せずにメニューからQUIT(終了)が選択されたら破棄するようにしないといけません。ちなみに、これを忘れるとメモリにゴミがたまっていき、最後にはシステムエラーで停止したりメモリ不足で何も起動できなくなったりします。こうなってしまったら再起動するしかありません。メモリ管理をしっかりしておかないと後で複雑なバグ(プログラムの間違い)を、引き起こすハメになってしまいます。

 EXIT FN命令は強制的にこの関数から抜け出す命令です。致命的なエラーなどの場合に、この命令を使用します。LONG IF〜XELSE〜END IF命令でネスティングが多くなると逆にバグの元になります。そのような場合は、このEXIT FNと組み合わせることでバグを回避できます。


◆最後に
 解説不足の所はありますが、それらに関しては次回以降で実例とともに説明したいと思います。Future BASICはC言語などと比べてかなり短い命令数(ステップ)でプログラムが実現できます。逆引きがあればいいのですが、それはいずれ用意したいと思います。


'------------------------------------------------------------- ' "PICTファイルをオープンしてウィンドウに描画する" '------------------------------------------------------------- LOCAL FN openPictFile DIM rect.8; f$ = FILES$(_fOpen,"PICT",,vRefNum%) LONG IF f$<>"" OPEN "I",#1, f$,,vRefNum% fileSize& = LOF(1,1) pictHandle& = FN NEWHANDLE(fileSize&+4) LONG IF pictHandle& err = FN HLOCK(pictHandle&) LONG IF err = 0 READ FILE#1, [pictHandle&], fileSize& BLOCKMOVE [pictHandle&]+512,[pictHandle&],fileSize& - 512 err = FN HUNLOCK(pictHandle&) err = FN SETHANDLESIZE(pictHandle&, fileSize&-512) err = FN HLOCK(pictHandle&) ptr& = [pictHandle&] pictLY% = PEEK WORD(ptr& + 6) pictLX% = PEEK WORD(ptr& + 8) '---------------------------------------------------- CLS: ' "ウィンドウ内容の消去" CALL SETRECT(rect,0,0,pictLX%,pictLY%) CALL DRAWPICTURE(pictHandle&,rect) '---------------------------------------------------- err = FN HUNLOCK(pictHandle&) END IF err = FN DISPOSHANDLE(pictHandle&) XELSE BEEP PRINT "メモリ不足じゃあ! メモリを増やさんかい!" EXIT FN END IF CLOSE #1 END IF END FN WINDOW #1,"Pict File View",(32,32)-(512+32,400+32),_docNoGrow FN openPictFile WHILE FN BUTTON = false:WEND END