// ( m6.C ) // マウスとキ−入力制御のノウハウ // #include #include // マウス入力している最中に、割込みでキ−入力したいとか、 #include // 数値入力をしたい場合があります。その制御方法を示します。 #include // これは参考書を見ても、なかなか分からないテクニックです。 #include // ついでに掲載しておきましたので、便利だから使ってネ!! #include char menue_cmd[20] ; // この2つの文字列で、Motifのメニュ−の何がセレクト char main_cmd[20] ; // されたか、判断するのだ。 class Motif { protected: Widget motif ; public: static XtAppContext appCon ; 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,(Cardinal*)&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 ) ; XtRealizeWidget( *topmf ) ; // これでMotifのメニュ−が表示される。 } } ; class Push: public Motif { char command[20] ; friend void push_cb( Widget,caddr_t,caddr_t ) ; public: 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() ; } class Text: public Motif { char str[80] ; friend void active_cb( Widget,caddr_t,caddr_t ) ; friend void modify_cb( Widget,caddr_t,caddr_t ) ; public: Text( Motif* pob,int xp,int yp ) ; ~Text() { del_widget() ; } int get_str( char* s ) { strcpy( s,str ) ; strcpy( str,"" ) ; if ( strcmp(s,"") != 0 ) return 0 ; // 文字列が保存された。 else return -1 ; // 文字列は保存されていない。 } void set_str( char* s ) { strcpy( str,s ) ; } void del_widget() { XtDestroyWidget( motif ) ; } } ; // 本当は Motif クラスに入れてしまおう。 Text::Text( Motif* pob,int xp,int yp ) { Arg args[7] ; Widget pid = pob->get_widget() ; strcpy( str,"" ) ; XtSetArg( args[0],XmNx,xp ) ; XtSetArg( args[1],XmNy,yp ) ; XtSetArg( args[2],XmNcursorPositionVisible,True ) ; XtSetArg( args[3],XmNeditable,True ) ; XtSetArg( args[4],XmNmaxLength,10 ) ; // 入力文字列の最大長さ XtSetArg( args[5],XmNtraversalOn,True ) ; // マウス入力中にキ−入力できるため // に必要である。 motif = XmCreateText( pid,NULL,args,6 ) ; XtManageChild( motif ) ; XtAddCallback( motif,XmNmodifyVerifyCallback,(XtCallbackProc)modify_cb,(caddr_t)this ) ; XtAddCallback( motif,XmNactivateCallback,(XtCallbackProc)active_cb,(caddr_t)this ) ; } void active_cb( Widget ww,caddr_t myself,caddr_t event ) { Text* text = (Text*)myself ; // リタ−ンキ−を押すと、アクティベイトが if ( text ) { // かかり、入力した文字列が保存される。 Widget temp = text->get_widget() ; text->set_str( XmTextGetString(temp) ) ; XmTextSetString( temp,"" ) ; } } void modify_cb( Widget ww,caddr_t myself,caddr_t event ) { char c ; // ここで文字列入力、数値入力、座標入力を Text* text = (Text*)myself ; // 制御する。バックスペ−スキ−などは長さ if ( text ) { // 0で入ってくる XmTextVerifyPtr vrfy = (XmTextVerifyPtr)event ; if ( vrfy->text->length >= 1 ) { c = *(vrfy->text->ptr) ; if (( c>='0' )&&( c<='9' )) { cout << "OK\n" ; cout.flush() ; } } } } class Draw: public Motif { public: Draw( 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 = XmCreateDrawingArea( pid,NULL,args,4 ) ; XtManageChild( motif ) ; } } ; class Mouse: public Motif { static Draw* draw ; // マウスのオブジェクトは、ただ1つしかないので static Text* text ; // とりあえず、静的指定にしておいた。 public: Mouse( Draw* da ) { draw = da ; } int action( int&,int&,Text* text=NULL ) ; } ; int Mouse::action( int& x,int& y,Text* text ) { Widget ddd = draw->get_widget() ; Window wbb = XtWindow( ddd ) ; XEvent event ; char sss[20] ; while ( True ) { XtAppNextEvent( appCon,&event ) ; if ( text != NULL ) { // キ−ボ−ド入力を横取りしてしまう。 if ( event.xany.type == KeyPress ) { XtSetKeyboardFocus( ddd,text->get_widget() ) ; XtDispatchEvent(&event); if ( text->get_str(sss) == 0 ) { cout << "key input : " << sss << endl ; cout.flush() ; if ( strcmp(sss,"100,100") == 0 ) { x=100;y=100; } return 1 ; } continue ; } } 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 ; } } } } Board* global_board ; Mouse* global_mouse ; void get_menue_command() { int x,y ; while ( True ) { if ( global_mouse->action(x,y) == 0 ) { strcpy( main_cmd,menue_cmd ) ; break ; } } } void line() { // Text ウィジットが出てきて、line() ル−チンを抜 Text ttt( global_board,10,60 ) ; // ける時に、ウィジットは自動的に消される。 int x1,y1 ; for ( ;; ) { if ( global_mouse->action( x1,y1,&ttt ) == 0 ) break ; cout << "line desu\n" ; cout.flush() ; } } void circle() { int x1,y1 ; for ( ;; ) { if ( global_mouse->action( 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() ; } } static String fallback[] = { "*XmBulletinBoard.traversalOn : False", // Text 入力に必要である。 "*XmDrawingArea.background : black", NULL } ; void main() { Top tp( "M5",fallback ) ; Board bd( &tp,0,0,500,500 ) ; Draw dw( &bd,0,200,470,270 ) ; Push p1( &bd,10,10,"LINE" ,"line" ) ; Push p2( &bd,80,10,"CIRCLE","circle" ) ; Mouse ms( &dw ) ; global_board = &bd ; global_mouse = &ms ; EXE_COMMAND() ; }