Macintosh Programming (9) - モードレスダイアログ - 2000.Sep. 1. 説明 ようやく、大昔に作ったリソース通りなウィンドウを作る時がきました。 全ソースはこちらからどーぞ。smpldlg.lzh.bin (8,960 bytes)。 ここで問題になるのはイベントループですね。参考文献やらサンプルソースを 見ると、ダイアログイベントを先に処理してからそこで処理できなかったものを 一般イベントで処理してます。が、それでは遅い。 main()で無惨にもコメントになっているのが参考書籍やIMに書かれている普通な 処理の流れです。 私があえて逆らったのは、enter押された時に先にダイアログマネージャに処理が 渡ったのではとっても困る。という事実から。 同じ処理を多重に書く気はしないし、(処理順を)逆にすればスマートに解決できる。 と思ったからです。 #う〜む。Window 3つ、ダイアログ3つを出る代物を仕事で作ったのだが、この 方法で破綻無く動いてますから結果オーケーでしょう。 他人はともかく、おいらはおいらで最善と思うコーディングをするとしよう。 深く気にしてハゲてもしょうがないからね(笑)... でも最近、抜け毛が多い。。。(泣)。いや。これから寒くなるんで、冬毛に 代わる途中かも。だってほら、色も白いのが混じるし……って、あれ?(号泣) 2. 自作関数の説明 ただしモーダルダイアログで出てこなかった関数のみ。 Boolean getNumber(Str255 ins, Boolean isHex, long *iret); 10進、あるいは16進文字列を数字に変換するっちゅー、Macとは関係ないルーチン void checkOption(DialogPtr dlg, short cClick, short* cCur); チェックボタンを選択するルーチン。その気になれば「現在選択されている場所」 なんぞを引数にしなくても良いんだけど、それだと全てのチェックボタンをいちいち 調べないといけないのでこーしました void invalEdit(DialogPtr dlg); KT7.5.5でEditBoxの上によそのウィンドウを載せる。で、そーっとずらすとEditの 枠がそこの部分だけ点線になっちまうんですな。これはみっともない。しかしOS 9では そーならない。いったいどうしたらよかんべぇ?とか色々やってこの関数にたどり 着いた。という訳です。もっと良い解決方法があるなら教えて(^^;; void doActivate(WindowPtr dlg, Boolean active); ダイアログ上のコントロールを順にたどってActive/Inactiveを切り替える。 void doMenu(int menu); メニュー処理。Aboutを出す時に本体ウィンドウをいったんInactiveにしてるのが ミソかも。あと、EditメニューでCut/Copy/Paste等を処理する必要もあります。 Boolean doMouseDown(EventRecord *event); inDrag、ウィンドウがドラッグされようとしている時に来る。 inGoAway、ウィンドウの左上、ゴーアウェイボックスでマウスクリックされた時に 来る。 こんなこともプログラム側で面倒みにゃならんのか。とため息が出ましたねあたしゃ(笑) Boolean doOK(DialogPtr dlg); OKが押された時の処理。 Boolean doKeyEvents(EventRecord* event); キーボードが押された時の処理 void doUpdateWindow(WindowRef win); ウィンドウの書き直しを行う。ここで、BeginUpdate()とEndUpdate()を呼んでいない点に ご注意。イベント処理手順を変えたこともあり、ここでこれらを呼ぶとダイアログ マネージャはもう自分の仕事はないと思ってダイアログを更新しなくなるんですな。 Boolean doHandleDlgEvent(EventRecord *event); ダイアログイベントの処理。本来はダイアログなのか?というIsDialogEvent()での 振り分けが必要だけど、このサンプルにはそもそも他のウィンドウがないので……。 Boolean doHandleEvents(EventRecord *event); ウィンドウとゆーかアプリに対して投げられるイベントを処理するルーチン。 void setDlgInitial(DialogPtr dlg); ダイアログの初期値を入れたりする。1度しか呼ばれない。 なお、curChange()、カーソルをI-ビームにする関数は前回の奴より進歩してます。 テキストエディットが何個あっても自動でサーチしてチェックします。 3. モーダルとの差 モードレスな場合、考慮すべきイベントは増えます。 ・他のアプリケーションのウィンドウがクリックされたなら、自分はインアクティブ にならなければならない (前にも触れたが、ウィンドウの中身を描き直すのはプログラマの責任である) ・他のウィンドウが自分の上に覆い被さってきたら、それに対応するのはもちろん、 他のウィンドウとやらが移動したらば、それまで隠されていた自分のウィンドウを 再描画しなけりゃならん ・困ったことにCut/Copy/Pasteの処理は自前でやらないとだめ 4. ノート あえて書くが、ParamText(0,0,0,0);とかやっちゃだめだ。ParamText()の4つの 引数はunsignd charなpascal文字列定数を期待してるんだから、それは0とは 違う。最低でも"\p"でなくてはならない。 つまりParamText("\p","\p","\p","\p");と書くべし。ということだ。 じゃないと妙な現象で悩むぞ〜。しばらく悩んだ本人が言うんだから間違い ありません(^_-)☆ (EOF)