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 が表示されます。めでたしめでたし。