Alertでトラップ(for only KT7.5.5) 手元にOS 8.xが転がっているなら、「おいらのプログラムはOS 8.x以降だけを サポートするよん(^^;;」とかうそぶいていられるのだが……。遺憾なことに、 自宅にあるのはKT7.5.5のみ。 会社のOS 9なマシンでは何の問題もないぞ。ってのも何か腹立たしいので、対策 してみました。 以下はつまりOS 8以降なら(OS 9以降か?もしかして)不要な処理ってこと。 ここで問題点とは: 「アラート表示中にESCキーを押しても(KT7だと)何も起こらない」 #実際にはESCだけでなくCommand + '.'にも対処する必要あり === 解決策はあります。前のソースでxxAlert(128, nil);って呼び出しをしてた でしょう? 「128」ってのはリソースの番号。それはよろしいですよね?では。nilは何かと 言えば、コールバック関数(Macではフィルタ関数と呼ぶようですが)のアドレスなん ですな(今更な蛇足ですが、nilってのは「0」の別名です)。 @コールバック関数って何? OSが勝手に何かやる前に(プログラマが)ちょっかいかけられる仕組み。ですな。 MacでもWindowsでもこういうのはまま、あります。ANSI Cでもqsortとかでコール バック関数が要求されます。OSなり、コンパイラなりに、必要なら呼び出して ね(はーと)とお願いするという代物です。 以下のソースは最初の、コールバック付きアラートの結果を次のコールバックなしの アラートで表示する。という極簡単なサンプルです。 ちなみにこのソース、68Kでコンパイルしないと動かないと思います(たとえPPCマシンで あっても)。やってみてないので本当かどうかは闇の中。ですけど。 で。普通Enter押すと[OK]ボタンが一瞬反転する。というリアクションが表示されるで しょう? Alert()の第2引数がnilの場合はプログラマは何もする必要、ありません。が。 コールバ、、あ。いえフィルタ関数を指定した場合、プログラマがその処理も肩代わり してやんなきゃならないようなんですな。 #信じられない。とか思ったけど、本当みたい。参考文献のサンプルもそーやってるし そのための関数がpushButton()。ちなみに反転時間である「8」というのはOSで定めて ある定数。確かUIガイドとかにもこの「8」という数字が直接書いてあった。 #何故、そんな大事な定数をユーザプログラム内で#defineしなきゃならんのだ?とか 思う?いや。私も同感なんだが……。そーゆーもんらしい。深く追求してないんで、 システムのincludeファイルのどっかに定義してあるのかもしれないけど。 余談だけど引数がintでなくshortってAPIが多いのはやっぱ128K Macな環境を連綿と 引きずっているからなんでしょうねぇ。 /* alerts */ #include <limits.h> #include <Resources.h> #include <Windows.h> //#include <Menus.h> #include <Dialogs.h> //#include <Devices.h> //#include <ToolUtils.h> //#include <Memory.h> //#include <Processes.h> //#include <SegLoad.h> //#include <Packages.h> //#include <Traps.h> QDGlobals qd; /* OS defined constants */ #define kVisualDelay 8 // Key push wait /* emulate button push */ static void pushButton(DialogPtr dlg, short item) { short cTyp; ControlHandle hCtl; Rect rc; unsigned long dmy; GetDialogItem(dlg, item, &cTyp, (Handle*) &hCtl, &rc); HiliteControl(hCtl, 1); Delay(kVisualDelay, &dmy); HiliteControl(hCtl, 0); } /* modal dialog filter */ static Boolean pascal dlgProc(DialogPtr theDlg, EventRecord *getEv, short *item) { //short iType; //Handle hCtl; //Rect rc; *item = 0; if (getEv->what == keyDown){ switch (getEv->message & charCodeMask){ case kEnterCharCode: // Enter case kReturnCharCode: // Return *item = ok; // == 1 break; case '.': // Command + '.' if (!(getEv->modifiers & cmdKey)) break; case kEscapeCharCode: // ESC *item = cancel; // == 2 }; if (*item != 0){ pushButton(theDlg, *item); return true; }; /* if ((getEv->message & keyCodeMask) == 0x3500){ // ESC //GetDialogItem(theDlg, 2, &iType, &hCtl, &rc); //HiliteControl((ControlHandle) hCtl, 10); *item = cancel+3; return true; }; switch (getEv->message & keyCodeMask){ case 0x4C00: // enter (13) case 0x2400: // return (3) //GetDialogItem(theDlg, 1, &iType, &hCtl, &rc); //HiliteControl((ControlHandle) hCtl, 10); // *item = ok+3; *item = getEv->message & charCodeMask; return true; }; if (((getEv->message & charCodeMask) == '.') && (getEv->modifiers & cmdKey)) { *item = cancel; return true; }*/ }; //theDlg = theDlg; // dummy for warning return false; } int main(void) { int iRet = 17; // no mean Str15 s; InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitCursor(); ParamText("\pfoo", "\pCaution", "\p", "\p"); iRet = CautionAlert(128, dlgProc); //sprintf((char*)s, ".#=%d", iRet); //s[0] = (unsigned char) strlen((char*) s+1); sprintf((char*)s, "#=%d", iRet); c2pstr(s); // C文字列からPascal文字列への変換。sprintf()の引数をコメントと // なっている2行と比較のこと!先頭の'.'がない点に注目 ParamText(s, "\pNote", "\p", "\p"); iRet = NoteAlert(128, nil); //ExitToShell(); return 0; } /* eof */ さて。このソースをコンパイルしてお試しあれ。KT7.5.5でも今度はちゃんとESCに 応答するでしょう? #え?動かないって?う〜む。もしかしてPPCマシンですか?だったら当然かも。68Kで コンパイルしてもらえます? 68Kマシンでは何も考えなくても良いソースがPPCマシンでは細工、しなきゃ動かない。って ことがあるようですから(コールバック関数とか……)。 #でもね。68Kでコンパイルしたら実行時エラーでOSが死にまくるのに、PPCでコンパイル したら何事もなく正常動作する。ってのも実際体験してる。 …これがまた、sprintf()なんだよな。こんな基本的なものでバグを出すってのは余程の間抜け だろうから、それはつまりあたしのミスなんだろうが良く分からない。 ところで。ResEditでアラートリソースを定義している時に、 ALRT->Set 'ALRT' Stage Infoを開いてみたかな?同じアラートが何度も出る場合に デフォルトボタンを変更したり、そもそも同じアラートが何度も出ること自体を 抑制できる。という機能です。 こんな機能、Windowsにはないです。う〜ん。便利と言うか何と言うか。 #余り何度もこれを実行してると何故かOSがすっ飛ぶみたい。何か非常に基本的なミスを犯して いるのでは?とか思ってますが、細かい所を気にしてても先に進めないので今は無視します。 (正しい理由をご存じの方はメールして教えて下さいませm(_o_)m) #ごちゃごちゃやってる部分がコメントになってますが、試行錯誤で悪戦苦闘した 様子をそのままお目にかけております(笑) 初めてのOSで初めての処理を作る場合、(あっしの場合は)これぐらい紆余曲折 するってことで(苦笑) (EOF)