X作成講座 on FB[08] 外部ウィンドウ パレット編[1]
今回はパレットタイプのウィンドウを作って、そこにピクトリソースを表示します。
ソース入力は全部で4つです。
まず例によって HyperXcmd.MAIN を書き換えます。 XCMD 名は "PicPalette" とでもしましょう。 ID は tasu と重複しないものを付けておいて下さい。
次にソースを分ける練習も兼ねて、自前のサブルーチンを myX.INCL というファイルに保存します。ソースが長くなる時はこのようにすると見通しが良くなります。
構造体をひとつ宣言するので、myX.GLBL というファイルも作ってみましょう。構造体宣言やグローバル宣言のような各ファイルから参照されるものは、このように独立したファイルにしておくと管理し易くなります。
最後にウィンドウのイベントを扱う HyperXcmd Events.INCL を書き換えます。外部ウィンドウの処理のほとんどはここに書くことになります。
この章では HyperXcmd.MAIN の書き換えと、myX.INCL、myX.GLBL の作成までを扱います。イベント処理は次の章にて。
−・−・−
まずメインルーチンを書き換えましょう。
HyperXcmd.MAIN の中で書き換えが必要なところを XonFB[02] に従って整えます。今回は XFCN ではなく XCMD として作ります。名前は "picPalette"、ID は tasu と重複しないものを付けて下さい。
自前のルーチンを別ファイルに作りますので、
00047 CASE ELSE 00048 'handle normal xcmd parametersの 00048 行を
00048 FN myX( xCmdPtr&, str255$(0), str255$(1) )とします。HyperTalk から受け取った2つの引数をそのままサブルーチンに渡しています。 xCmdPtr& も一緒に渡すのをお忘れなく。
00013 INCLUDE "HyperXcmd Events.INCL" 'load your own xcmd routinesのあとに
INCLUDE "myX.INCL"という一行を加えます。
00001 ' 00002 ' myX.INCL 00003 ' 00004 ' -------------------------------- 00005 00006 INCLUDE FILE _resIncl 00007 00008 GLOBALS "HyperXcmd.GLBL" 00009 GLOBALS "myX.GLBL" 00010 END GLOBALS 00011 INCLUDE "HyperXcmd Glue.INCL" 00012 00013 00014 00015 ' --------------------- FUNCTIONS ----------------------- 00016 ' err message 00017 LOCAL FN setErr( xCmdPtr&, errMes$ ) 00018 xCmdPtr&.returnValue& = FN PasToZero ( xCmdPtr&, errMes$ ) 00019 END FN 00020 00021 ' main function 00022 LOCAL FN myX( xCmdPtr&, tgPic$, myLoc$ ) 00023 DIM picRect.8 00024 DIM myPt.4 00025 00026 ' get PICT resource id 00027 CALL SETRESLOAD( _false ) 00028 resHand& = FN GETNAMEDRESOURCE( _"PICT", tgPic$ ) 00029 LONG IF resHand& = 0 00030 resHand& = FN GETRESOURCE( _"PICT", FN StrToNum( xCmdPtr&, tgPic$ ) ) 00031 END IF 00032 CALL SETRESLOAD( _zTrue ) 00033 LONG IF resHand& = 0 00034 FN setErr( xCmdPtr&, "Error : Not found PICT resource" ) 00035 EXIT FN 00036 END IF 00037 CALL GETRESINFO( resHand&, resID%, resType&, title$ ) 00038 ' 00039 ' get PICT handle 00040 picHand& = FN GETPICTURE( resID% ) 00041 LONG IF picHand& = 0 00042 FN setErr( xCmdPtr&, "Error : Not enough memory" ) 00043 EXIT FN 00044 END IF 00045 picHand& = FN HANDTOHAND( picHand& ) 00046 LONG IF picHand& = 0 00047 FN setErr( xCmdPtr&, "Error : Not enough memory" ) 00048 EXIT FN 00049 END IF 00050 ' 00051 ' get PICT rect 00052 picRect;8 = [ picHand& ] + _picFrame 00053 ' 00054 ' create window 00055 xWndPtr& = FN NewXWindow ( xCmdPtr&, picRect, title$, _false, _palNoGrowProc_toggleHilite, _zTrue, _zTrue ) 00056 LONG IF xWndPtr& = 0 00057 FN setErr( xCmdPtr&, "Error : Can't create window" ) 00058 EXIT FN 00059 END IF 00060 ' 00061 ' set window location 00062 FN StrToPoint( xCmdPtr&, myLoc$, myPt ) 00063 CALL LOCALTOGLOBAL( myPt ) 00064 CALL MOVEWINDOW( xWndPtr&, myPt.h, myPt.v, _false ) 00065 ' 00066 ' set my data to window's refCon 00067 myDataHand& = FN NEWHANDLE( 4 + 4 ) 00068 myDataHand&..fPicHand& = picHand& 00069 creator$ = "Who" 00070 myDataHand&..fCreatorHand& = FN PasToZero( xCmdPtr&, creator$ ) 00071 CALL SETWREFCON( xWndPtr&, myDataHand& ) 00072 END FN 00073
00008 GLOBALS "HyperXcmd.GLBL" 00009 GLOBALS "myX.GLBL" 00010 END GLOBALS 00011 INCLUDE "HyperXcmd Glue.INCL"最初に必要なグローバル変数ファイルを読み込みます。 XCMD を作るときは HyperXcmd.GLBL は必須です。今回は myX.GLBL というファイル(あとで作ります)も読み込みます。
00016 ' err message 00017 LOCAL FN setErr( xCmdPtr&, errMes$ ) 00018 xCmdPtr&.returnValue& = FN PasToZero ( xCmdPtr&, errMes$ ) 00019 END FNエラーメッセージを HyperTalk の読めるところに書き込むためのルーチンです。リソースを使わずに直接 HyperTalk に文字列を返したい時はこのようにします。今回は独自のエラーメッセージはこのルーチンを使って HyperTalk に返しています。他のテンプレートで処理しているメッセージはそのままです。(手抜きです(^^;))
00021 ' main function 00022 LOCAL FN myX( xCmdPtr&, tgPic$, myLoc$ ) 00023 DIM picRect.8 00024 DIM myPt.4ここからサブルーチンがスタートします。 tgPic$ には HyperTalk から渡された第1引数が入ります。同様に、myLoc$ には第2引数の文字列が入ります。
00026 ' get PICT resource id 00027 CALL SETRESLOAD( _false ) 00028 resHand& = FN GETNAMEDRESOURCE( _"PICT", tgPic$ ) 00029 LONG IF resHand& = 0 00030 resHand& = FN GETRESOURCE( _"PICT", FN StrToNum( xCmdPtr&, tgPic$ ) ) 00031 END IF 00032 CALL SETRESLOAD( _zTrue ) 00033 LONG IF resHand& = 0 00034 FN setErr( xCmdPtr&, "Error : Not found PICT resource" ) 00035 EXIT FN 00036 END IF 00037 CALL GETRESINFO( resHand&, resID%, resType&, title$ )この XCMD では第1引数にリソース名、もしくはリソース ID を渡すことが出来ます。指定されたリソースの ID を得るには、以下の手順を踏みます。
00039 ' get PICT handle 00040 picHand& = FN GETPICTURE( resID% ) 00041 LONG IF picHand& = 0 00042 FN setErr( xCmdPtr&, "Error : Not enough memory" ) 00043 EXIT FN 00044 END IF 00045 picHand& = FN HANDTOHAND( picHand& ) 00046 LONG IF picHand& = 0 00047 FN setErr( xCmdPtr&, "Error : Not enough memory" ) 00048 EXIT FN 00049 END IF先ほど得ておいた resID% を使って、ToolBox の GetPicture で PICT リソースを読み込みます。読み込んだ上で、更に ToolBox の HandToHand で複製しておきます。リソースのハンドルはいつ誰に破棄されるか分からないので、こうして独立したハンドルとして保持しておくのが確実です。
00051 ' get PICT rect 00052 picRect;8 = [ picHand& ] + _picFrameウィンドウの大きさを決定するために、読み込んだピクトのサイズを得ます。ピクトリソースはオフセット _picFrame の位置に自身のレクト情報を持っているので、これを picRect へ転送します。このレクトはそのままウィンドウの大きさとして使います。
00054 ' create window 00055 xWndPtr& = FN NewXWindow ( xCmdPtr&, picRect, title$, _false, _palNoGrowProc_toggleHilite, _zTrue, _zTrue ) 00056 LONG IF xWndPtr& = 0 00057 FN setErr( xCmdPtr&, "Error : Can't create window" ) 00058 EXIT FN 00059 END IF実際にウィンドウを作っています。 ToolBox の解説書では NewWindow を使え、と書いてあると思いますが、XCMD ではグルールーチンの NewXWindow を使います。(同様に、ウィンドウの破棄は CloseWindow ではなく CloseXWindow です) 外部ウィンドウは HyperCard が管理するウィンドウなので、プログラマが勝手に作ったり破棄したりしてはいけません。 HyperCard に「作って下さい」「破棄して下さい」とお願いするのです。
00061 ' set window location 00062 FN StrToPoint( xCmdPtr&, myLoc$, myPt ) 00063 CALL LOCALTOGLOBAL( myPt ) 00064 CALL MOVEWINDOW( xWndPtr&, myPt.h, myPt.v, _false )この XCMD では第2引数にウィンドウの座標を指定することが出来ます。ここでは作成したウィンドウの座標を指定座標に移動する処理をしています。
00066 ' set my data to window's refCon 00067 myDataHand& = FN NEWHANDLE( 4 + 4 ) 00068 myDataHand&..fPicHand& = picHand& 00069 creator$ = "Who" 00070 myDataHand&..fCreatorHand& = FN PasToZero( xCmdPtr&, creator$ ) 00071 CALL SETWREFCON( xWndPtr&, myDataHand& )さてこれがまたちょっとややこしいのですが・・・ ToolBox の SetWRefCon を使って、ウィンドウの "refCon" に独自のデータのハンドルを書き込んでいます。
DIM RECORD myDataRec DIM fPicHand& DIM fCreatorHand& DIM END RECORD .myDataRecというレコードを宣言します。
' ' myX GLBL '------------------------------- DIM RECORD myDataRec DIM fPicHand& DIM fCreatorHand& DIM END RECORD .myDataRecなぜ myX.INCL 内に入れてしまわないかと言うと、この構造体はイベント処理時にも使うので、HyperXcmd Events.INCL からも読み込むからです。いくつかのファイルから共通で利用するグローバル変数や構造体は、このように別ファイルで管理するのが良いですね。