X作成講座 on TC(11) 外部ウィンドウのプロパティ
今回は外部ウィンドウにプロパティを持たせる方法を説明します。プロパティの取得/設定もイベントの一種なのですが、マニュアルの記述だけでは分かりにくいところもあるようなので、ここにサンプルを載せます。
今回作るXは、picID というプロパティを持った外部ウィンドウを作ります。 set the picID of window "myWin" to 500 などと実行すると、ウィンドウのピクトが変更される訳です。ソースは X on TC [07] にあるドキュメントウィンドウを改造したもので、プロパティ処理以外は基本的に同じです。変更した部分に ***** を付けてあります。
// -------------------------------------- // xDocWin template 2000.6.14 ( c )UDI // for THINK C 7.1 // -------------------------------------- #include "HyperXCmd.h" #include "SetUpA4.h" /* Prototypes */ void createWindow( XCmdPtr paramPtr ); void doEvent( XCmdPtr paramPtr ); WindowPtr getWinPtr( Str255 targetStrName ); typedef struct { //****** short picID; PicHandle picHand; } myData; pascal void main( XCmdPtr paramPtr ){ RememberA0( ); SetUpA4( ); if ( paramPtr->paramCount > -1 ){ createWindow( paramPtr ); } else { doEvent( paramPtr ); } RestoreA4( ); } void createWindow( XCmdPtr paramPtr ){ Str255 tempStr, winName; short theLeft, theTop, theRight, theBottom, picID; Rect winRect; PicHandle myPicHand; WindowPtr myWindowPtr; myData **myDHand; //***** ZeroToPas( paramPtr, *paramPtr->params[0], winName ); if( getWinPtr( winName ) ){ SysBeep(1); return; } ZeroToPas( paramPtr, *paramPtr->params[1], tempStr ); picID = StrToNum( paramPtr, tempStr ); myPicHand = GetPicture( picID ); if ( myPicHand == nil ){ paramPtr->returnValue = PasToZero( paramPtr, "\pNot found pict" ); return; } if ( paramPtr->paramCount > 2 ){ ZeroToPas( paramPtr, *paramPtr->params[2], tempStr ); StrToRect( paramPtr, tempStr, &winRect ); } else { winRect = ( **myPicHand ).picFrame; OffsetRect( &winRect, 100,100 ); // move winRect anyplace } myWindowPtr = NewXWindow(paramPtr, &winRect, winName, false, 8, true, false); if ( myWindowPtr == nil ){ paramPtr->returnValue = PasToZero( paramPtr, "\pCan't create win" ); return; } myDHand = ( myData**)NewHandle( sizeof( myData ) ); //**** ( *myDHand )->picHand = myPicHand; //**** ( *myDHand )->picID = picID; //**** SetWRefCon( myWindowPtr, ( long )myDHand ); } void doEvent( XCmdPtr paramPtr ){ GrafPtr savePort; EventRecord myEvent; WindowPtr myWindowPtr; XWEventInfoPtr myXWEventInfoPtr; PicHandle myPicHand; myData **myDHand; //***** Str255 *propNamePtr, theStr; //***** myXWEventInfoPtr = ( XWEventInfoPtr)(paramPtr->params[0] ); myWindowPtr = myXWEventInfoPtr->eventWindow; myEvent = myXWEventInfoPtr->event; GetPort( &savePort) ; SetPort( myWindowPtr ); switch ( myEvent.what ){ case mouseDown: switch ( FindWindow( myEvent.where, &myWindowPtr ) ){ case inGoAway: // closeBox if ( TrackGoAway( myWindowPtr, myEvent.where ) ){ CloseXWindow( paramPtr, myWindowPtr ); } break; case inDrag: // titleBar paramPtr->passFlag = true; break; case inContent: // window content SelectWindow( myWindowPtr ); break; } break; case xOpenEvt: XWAllowReEntrancy(paramPtr, myWindowPtr, true, true); ShowWindow( myWindowPtr ); paramPtr->passFlag = true; break; case xCloseEvt: paramPtr->passFlag = true; break; case updateEvt: BeginUpdate( myWindowPtr ); myDHand = ( myData** )GetWRefCon( myWindowPtr ); //***** myPicHand = ( *myDHand )->picHand; //***** DrawPicture( myPicHand, &( **myPicHand ).picFrame ); EndUpdate( myWindowPtr ); break; case activateEvt: break; case app4Evt: break; case xCursorWithin: paramPtr->passFlag = true; // change arrowCursor by HC break; case xGetPropEvt: //***** propNamePtr = ( Str255*)myXWEventInfoPtr->eventParams[0]; if ( EqualString( *propNamePtr, "\ppicID", false, false ) ){ myDHand = ( myData** )GetWRefCon( myWindowPtr ); NumToStr( paramPtr, (*myDHand)->picID, theStr ); myXWEventInfoPtr->eventResult = PasToZero( paramPtr, theStr ); paramPtr->passFlag = false; break; } paramPtr->passFlag = true; break; case xSetPropEvt: //***** propNamePtr = ( Str255*)myXWEventInfoPtr->eventParams[0]; if ( EqualString( *propNamePtr, "\ppicID", false, false ) ){ ZeroToPas( paramPtr, *( Handle)( myXWEventInfoPtr->eventParams[1] ), theStr ); myDHand = ( myData** )GetWRefCon( myWindowPtr ); (*myDHand)->picID = StrToNum( paramPtr, theStr ); myPicHand = GetPicture( (*myDHand)->picID ); (*myDHand)->picHand = myPicHand; SizeWindow( myWindowPtr, ( *myPicHand )->picFrame.right, ( *myPicHand )->picFrame.bottom, false ); InvalRect( &( myWindowPtr->portRect ) ); paramPtr->passFlag = false; break; } paramPtr->passFlag = true; break; } SetPort( savePort ); } WindowPtr getWinPtr( Str255 targetStrName ){ Str255 titleStr; WindowPtr theWinPtr; theWinPtr = ( WindowPtr)LMGetWindowList(); while( theWinPtr ){ GetWTitle( theWinPtr, titleStr ); if( EqualString( targetStrName, titleStr, true, true ) ){ return theWinPtr; } theWinPtr = ( WindowPtr)( ( ( CWindowPeek)theWinPtr )->nextWindow ); } return ( WindowPtr)0; }
typedef struct { //****** short picID; PicHandle picHand; } myData;ここでは自分のデータを入れるための構造体を宣言しています。今回はウィンドウに表示するピクトのIDをプロパティとして持たせるので、ピクトIDを入れる short と、ピクトのハンドルを入れる PicHandle型のメンバーを作っておきます。
myData **myDHand; //*****を宣言しておきます。 myDHand というハンドル変数が指している先は myData であるという意味ですね。
myDHand = ( myData**)NewHandle( sizeof( myData ) ); //**** ( *myDHand )->picHand = myPicHand; //**** ( *myDHand )->picID = picID; //**** SetWRefCon( myWindowPtr, ( long )myDHand );まず NewHandle で自分のデータを格納するメモリブロックを作ります。それから picHandメンバーにピクトのハンドル、picIDメンバーにはピクトのIDを入れます。そしてこのメモリブロックのハンドルを、refCon に入れます。 X on TC [07] の時に比べてワンクッション余分に入っていることになります。こうすることによって、4バイトを越えるデータを refCon に保存することが出来ます。 refCon は long型で定義されているので、myDHand は long にキャストしています。
case updateEvt: BeginUpdate( myWindowPtr ); myDHand = ( myData** )GetWRefCon( myWindowPtr ); //***** myPicHand = ( *myDHand )->picHand; //***** DrawPicture( myPicHand, &( **myPicHand ).picFrame ); EndUpdate( myWindowPtr ); break;
case xGetPropEvt: //***** propNamePtr = ( Str255*)myXWEventInfoPtr->eventParams[0]; if ( EqualString( *propNamePtr, "\ppicID", false, false ) ){ myDHand = ( myData** )GetWRefCon( myWindowPtr ); NumToStr( paramPtr, (*myDHand)->picID, theStr ); myXWEventInfoPtr->eventResult = PasToZero( paramPtr, theStr ); paramPtr->passFlag = false; break; } paramPtr->passFlag = true; break;HyperTalk から get the [propName] of window [winName] が実行されると、イベントとして xGetPropEvt が送られて来ます。この時の [propName] に相当するプロパティ名は、( Str255*)myXWEventInfoPtr->eventParams[0] で取り出すことが出来ます。
case xSetPropEvt: //***** propNamePtr = ( Str255*)myXWEventInfoPtr->eventParams[0]; if ( EqualString( *propNamePtr, "\ppicID", false, false ) ){ ZeroToPas( paramPtr, *( Handle)( myXWEventInfoPtr->eventParams[1] ), theStr ); myDHand = ( myData** )GetWRefCon( myWindowPtr ); (*myDHand)->picID = StrToNum( paramPtr, theStr ); myPicHand = GetPicture( (*myDHand)->picID ); (*myDHand)->picHand = myPicHand; SizeWindow( myWindowPtr, ( *myPicHand )->picFrame.right, ( *myPicHand )->picFrame.bottom, false ); InvalRect( &( myWindowPtr->portRect ) ); paramPtr->passFlag = false; break; } paramPtr->passFlag = true; break;HyperTalk から set the [propName] of window [winName] to [value] が実行されると、この xSetPropEvt が送られて来ます。
xWin "testWin", 1000を実行すると、id 1000 のピクトを表示する外部ウィンドウが現れます。前回のXと同じ動作ですね。このウィンドウを表示させたままで、
set the picID of window "testWin" to 1001を実行すると、id 1001 のピクトが表示され、ピクトに合わせてウィンドウの大きさも変更されます。ウィンドウ内全体がちゃんと描き直されるのは、InvalRect を実行しておいたお陰です。(これをコメントアウトするとどうなるか実験するのも面白いです) プロパティがどうなっているか確認するために、
put the picID of window "testWin"を実行してみます。変更後の id である 1001 が表示されます。めでたしめでたし。