|
今回は、小ネタです。 現在、とあるアプリを作成中ですが、その中で気が付いた事がありましたので、ネタにしてみました。 Palmのアプリを使っていて、あまり気にならないのが、アプリの切り替えですね。 ハードキーを押すか、ホームをタップすれば、大抵の場合、アプリの切り替えが可能で、その高速さがPalmの「ウリ」でもあります。 私は、Palmのアプリが「最終状態が自動的に保持され、自動的に起動時に再現される」という動きに見えましたので、OSがそれらをサポートしていると思い込んでいましたが、NS Basicを触るようになって、自分でしなきゃダメ!、ということを知りました。 そこで、AmiSolは、起動時にDBを読み取り、終了時にDBに保存するように作りました。が、BASICの宿命でしょうか(?)切り替えが若干遅いような気がします。 終了時の状態を一気にDBに保存しようとするから、遅くなるのかもしれませんね。では、実行時、その都度DBへアクセスすれば終了時のもたつきは解消できるでしょうか? 答えは「引き分け」です。 AmiSolが使っている比較的大きな配列変数、NS Basicはそれらへのアクセスがあまり早くない気がしますので、ゲームの速度が遅くなる可能性があるわけです。 一方、速度が問題にならない場合や、直接データをDBへ保存するだけの場合、随時タイプの方が良いでしょう。 ということで、引き分けなのです。 さて、終了時に何らかの処理をする場合、NS Basicでは、Terminationというイベントを利用します。Terminationは、Startupの逆で、終了時に実行されるコードです。 ハンドブックでは「データベースの終了などの、終了プログラムの実行が行えます。」と記述があります。 AmiSolでも、Termination Codeに、 Res=DbUpdate(AmiSolDb,"100",Lefcoma,Putmode,SoundMode,Sol,Apx,Apy) Res=DbUpdate(AmiSolDb,"101",undo_flg,undo_x1,undo_y1,undo_x2,undo_y2)というような状態を保存する処理が行われています。 今回作っているアプリは、AmiSolの10倍程度の大きな配列を使って作っていますが、配列を処理してDBへ保存するだけで結構な時間がかかるようになりました。 Windows上の「お待ち下さい」というよりは待ちませんが、Palm上では「したいことが、即できる」という操作に慣れていますので、我慢できない速度です。 そこで、苦肉の作として、Windowsアプリのように「データを保存してから終了しますか?」というダイアログを表示して、保存したいときだけ保存する仕様にしました。 このような、ダイアログとして簡単なものは、Alert()という関数です。 Alert(タイトル名,コメント,タイプ,ボタン文字1,ボタン文字2,...,ボタン文字N) という関数で、戻り値は「ボタン文字N」のボタンをタップしたら、N−1、が戻ってきます。 例えば、
Res = Alert("Save Data","Do you wish to save data?",1,"Yes","No")
この状態で「Yes」をタップすれば、Resに「0」が返る、という具合です。では、Termination Codeにこれを実装してみましょう。 ・・・実行中・・・・ありゃ?! 一瞬、ダイアログのようなものが表示されたけど、終わってしまいました。 同様に、MsgBoxでも試してみましたが、ありゃ?!でした。 ダイアログらしきものが表示されるので、Form自体はまだ、存在しているのでしょうか?とにかく、ダイアログは使えない状態です。 キー入力を受け付けないのかなぁ。ということです。 「じゃあ、フォームのイベント内でダイアログ処理すれば良いじゃん!」 と思われるかもしれません。そう、ホームをタップしたイベントで取れば良い訳です。 ところで、ハードキーなどを使ったアプリには2種類のアプリが考えられます。1つは、ゲームのように、ハードキーを駆使してホーム以外のキーはアプリ用の機能を割り当てる場合、もう1つは、ハードキーがそのまま有効な場合で、MEMOを押したらメモ帳が起動する場合です。 後者の場合は、キー自体のイベントの処理がありませんので、イベントコード内にAlertなどを実装すればOKです。 前者の場合は、やや注意が必要です。 ゲームなどで、前進、後進、右、左などにキーを割り当てると、たいてい次のようなコードになると思います。
strkey=GetKey()
Select Case strKey
Case &h1 'Shoot
Call Shoot()
Case &h4 'Shoot
Call Shoot()
Case &h2 'move Left
Px(2)=Px(2)-1
Case &h3 'move Right
Px(2)=Px(2)+1
Case &hb 'move Up
Py(2)=Py(2)-1
Case &hc 'move Down
Py(2)=Py(2)+1
Case &h6
Stop
Case &h11
Stop
End Select
SetEventHandled
(STOPのキーコードが &H6と &H11(17)の2つがあるのは、ランタイムのバージョン1.10対策です。)ハードキーを支配するときのポイントはSetEventHandledですね。OS側の処理を無効にしますので、MEMOを押してもメモ帳が起動しなくなります。 一方、ホームを押してもホームに戻らなくなるため、STOPの処理が必要なわけですね。(「06) ホントは好きじゃないの」参照) さて、「ホントは好きじゃないの」の時は、気が付かなかったことなのですが、SetEventHandledがOS側の割り込みを無効にするだけではなくて、NS Basicコマンドの「STOP」まで無効にしてしまうようなのです。
strkey=GetKey()
SetEventHandled
Select Case strKey
Case &h1 'Shoot
Call Shoot()
Case &h4 'Shoot
(中 略)
Case &h6
Stop
Case &h11
Stop
End Select
こうすると、STOPコマンドが動かないんですね。それどころか、SetEventHandled後のSTOPは、アプリを固まらせるようです。無理矢理終わろうとしてるんでしょうか、リセットしなければならない危険なアプリになってしまいます。(バグかなぁ?)とにもかくにも、SetEventHandledは、処理が終わってからの、End Subに近い方がよさそうですね。 さて、まとめです。 Termination Code内では、入力系のAlert()やMsgBox()を無視して、さっさと終わろうとするので、イベントコード内でトラップするようにしましょう。ということです。 また、そのイベント内では、SetEventHandledの位置に気を付けよう、ということも追加しておきます。 (現在作成中のアプリは、上手くいけば今週中に公開しますが、夜桜が私を呼んでいるので、期待しないで下さいね。) |