// ( m5.C ) // イベント制御のノウハウ(ちょっと長いけど見てネ) // #include // Motifのイベント制御は、普通にやると結構難しいです。 #include // ここで紹介する方法でやれば、直感的で分かりやすくなりま #include // す。またMotifのクラス・ライブラリを作る場合のモデ #include // ルも示しました。がんばって作成して下さい。Good Luck !! char menue_cmd[20] ; // この2つの文字列で、Motifのメニュ−の何がセレクト char main_cmd[20] ; // されたか、判断するのだ。 class Motif { protected: Widget motif ; public: static XtAppContext appCon ; static Widget base_board ; // ブリテンボ−ドのベ−ス static Widget* topmf ; Widget get_widget( void ) { return motif ; } } ; class Top: public Motif { public: Top( char*,String[] ) ; } ; Top::Top( char* rname,String fallback[] ) // ア−ギュメントを強制的にセットしている { // ところがミソなのだ。 int argc = 1 ; char* argv[1] ; strcpy( argv[0],"" ) ; // プログラム名は渡さない motif = XtAppInitialize( &appCon,rname, // リソ−ス名 NULL,0,&argc,argv,fallback,NULL,0 ) ; topmf = &motif ; } class Board: public Motif { public: Board( Motif* pob,int px,int py,int width,int height ) { Arg args[4] ; Widget pid = pob->get_widget() ; XtSetArg( args[0],XmNx,px ) ; XtSetArg( args[1],XmNy,py ) ; XtSetArg( args[2],XmNwidth,width ) ; XtSetArg( args[3],XmNheight,height ) ; motif = XmCreateBulletinBoard( pid,NULL,args,4 ) ; XtManageChild( motif ) ; base_board = motif ; XtRealizeWidget( *topmf ) ; // これでMotifのメニュ−が表示される。 } } ; class Push: public Motif { char command[20] ; friend void push_cb( Widget,caddr_t,caddr_t ) ; public: Push() {} Push( Motif* pob, // 親オブジェクト int xp,int yp, // ボタンを表示するX、Y座標 char* str, // ボタンの中に表示する文字列(リソ−ス優先) char* cmd ) ; // ボタンを押して実行するコマンド名 void pushCB( void ) { strcpy( menue_cmd,this->command ) ; } } ; Push::Push( Motif* pob,int xp,int yp,char* str,char* cmd ) { strcpy( command,cmd ) ; Widget pid = pob->get_widget() ; Arg args[2] ; XtSetArg( args[0],XmNx,xp ) ; XtSetArg( args[1],XmNy,yp ) ; motif = XmCreatePushButton( pid,str,args,2 ) ; XtManageChild( motif ) ; XtAddCallback( motif,XmNactivateCallback,(XtCallbackProc)push_cb,(caddr_t)this ) ; } void push_cb( Widget ww,caddr_t myself,caddr_t event ) { Push* push = (Push*)myself ; if ( push ) push->pushCB() ; } int hit_button( int &x,int &y ) { Window wbb = XtWindow(Motif::base_board) ; // GUIのベ−ス XEvent event ; while ( True ) { XtAppNextEvent( Motif::appCon,&event ) ; XtDispatchEvent( &event ) ; if ( strcmp(menue_cmd,"") != 0 ) { // メニュ−が何かセレクトされた cout << "exit routine\n" ; cout.flush() ; return 0 ; } if ( event.xbutton.window == wbb ) { if ( event.xany.type == ButtonPress ) { x = event.xbutton.x ; y = event.xbutton.y ; return 1 ; } } } } void get_menue_command() { int x,y ; while ( True ) { if ( hit_button(x,y) == 0 ) { strcpy( main_cmd,menue_cmd ) ; break ; } } } void line() // 中味はお好きなように! { int x1,y1 ; for ( ;; ) { if ( hit_button( x1,y1 ) == 0 ) break ; cout << "line desu\n" ; cout.flush() ; } } void circle() { int x1,y1 ; for ( ;; ) { if ( hit_button( x1,y1 ) == 0 ) break ; cout << "circle desu\n" ; cout.flush() ; } } void EXE_COMMAND( void ) { get_menue_command() ; while ( True ) { strcpy( main_cmd,menue_cmd ) ; strcpy( menue_cmd,"" ) ; if ( strcmp(main_cmd,"line" )==0 ) line() ; else if ( strcmp(main_cmd,"circle")==0 ) circle() ; } } class Gui { // M5 というのは .Xdefaults で指定する名前なのだ。わかるかな? public: Gui( int x1,int y1,int x2,int y2,String fallback[] ) { Top *t = new Top( "M5",fallback ) ; // Motif の初期状態をセットする Board *base = new Board( t,x1,y1,x2,y2 ) ; // 画面の大きさをセットする new Push( base,30,10," LINE ","line" ) ; new Push( base,30,60," CIRCLE ","circle" ) ; } } ; static String fallback[] = { "*XmPushButton.foreground : yellow", "*XmPushButton.background : red", "*XmPushButton.shadowThickness : 4", NULL } ; void main() { Gui gui( 0,0,200,200,fallback ) ; EXE_COMMAND() ; }