シリーズ仕様書からプログラムソースを生成する方法の続きです。
前のところで、「具体的に」ということだったので、実際に、メニュー項目を入れる話をやってみましょう。
メニュー項目に限らず、このような、雛形があって、そこから、自動生成する場合については、以下のような手順で考えると、考えやすいと思います。
1.仕様を決める
2.仕様を満たすためには、どういう出力をすればいいか-出力ソースサンプルを作る
3.サンプルをもとに雛形を作る
4.雛形から、出力にもってくるプログラム部分を作成する。
まず、今回は1と2について考えます。
■1.仕様
以下のような画面定義をすると
以下のようなメニューの画面
を表示します。
なお、今回は、イベント処理は置いておきます
(他のシリーズでイベント処理についてやっています。
このシリーズが終わったころに、
そっちのシリーズと合流して、イベント処理を追加する予定です)
■2.出力ソースサンプル
仕様書からBREWのソースファイル自動生成で公開したもの(リンク先の一番下のダウンロード)を使って、
まず、以下のように、なにも入れないで、第一画面を作成し、
その後、仕様を満たすようにgamen1.c,gamen1.hを、以下のように修正します
(それ以外の、fukusu2.c,fukusu2.h,version.h,IHtmlCtl.h,IHtmlCtl.c,IKHMap.c,IKHMap.hは、修正しないでメンバーに追加します。fukusu2.bid,fukusu2.mifファイルはMIFエディタを使ってあらかじめ作成しておいてください)
●ヘッダファイル(gamen1.h)
/*======================================== FILE: gamen1.h =========================================*/ #ifndef _GAMEN1_H #define _GAMEN1_H /*========================================== INCLUDES AND VARIABLE DEFINITIONS =========================================== */ #include "AEEModGen.h" // Module interface definitions #include "AEEAppGen.h" // Applet interface definitions #include "AEEShell.h" // Shell interface definitions #include "AEEMenu.h" #include "fukusu2.h" // アプリ画面 //==================================// // 定数定義 // //==================================// typedef struct _gamen1 { IDisplay *pIDisplay; IShell *pIShell; IMenuCtl *pMenu1; } gamen1; /*------------------------------------ Function Prototypes ---------------------------------------*/ #ifdef _GAMEN1_C boolean gamen1_HandleEvent(fukusu2* poya, AEEEvent eCode, uint16 wParam,uint32 dwParam); boolean gamen1_InitAppData(fukusu2* poya); void gamen1_FreeAppData(fukusu2* poya); // 画面表示 boolean gamen1_DispAppData(gamen1* pMe); #else extern boolean gamen1_HandleEvent(fukusu2* pMe, AEEEvent eCode, uint16 wParam,uint32 dwParam); extern boolean gamen1_InitAppData(fukusu2* pMe); extern void gamen1_FreeAppData(fukusu2* pMe); // 画面表示 extern boolean gamen1_DispAppData(gamen1* pMe); #endif #endif |
(上記のプログラム中の< > ¥は、本当は半角です)
●ソースファイル(gamen1.c)
/*================================ FILE: gamen1.c =================================*/ #define _GAMEN1_C #include "gamen1.h" /*==================================*/ // 関数名:gamen1_HandleEvent // // 内容 :イベント処理 // /*==================================*/ boolean gamen1_HandleEvent(fukusu2* poya, AEEEvent eCode, uint16 wParam, uint32 dwParam) { gamen1 *pMe; // チェック if ( poya == NULL ) return FALSE; if ( ( poya->gno != 1 ) || (poya->garea == NULL )) return FALSE; pMe = (gamen1 *)poya->garea; // 追加:テキストエリア if ( pMe->pMenu1 != NULL ) { if ( IMENUCTL_HandleEvent(pMe->pMenu1, eCode,wParam,dwParam) == TRUE ) { return TRUE; } } switch (eCode) { // App is told it is starting up case EVT_APP_START: // Add your code here... return(TRUE); // App is told it is exiting case EVT_APP_STOP: // Add your code here... return(TRUE); // App is being suspended case EVT_APP_SUSPEND: // Add your code here... return(TRUE); // App is being resumed case EVT_APP_RESUME: // Add your code here... return(TRUE); // An SMS message has arrived for this app. // Message is in the dwParam above as (char *) // sender simply uses this format "//BREW:ClassId:Message", // example //BREW:0x00000001:Hello World case EVT_APP_MESSAGE: // Add your code here... return(TRUE); // A key was pressed. Look at the wParam above // to see which key was pressed. The key // codes are in AEEVCodes.h. // Example "AVK_1" means that the "1" key was pressed. case EVT_KEY: // Add your code here... return(TRUE); case EVT_COMMAND: switch(wParam) { case 2000: gamen1_FreeAppData(poya); poya->gno = -1; return TRUE; } break; default: break; } return FALSE; } /*==================================*/ //関数名:gamen1_InitAppData // //内容 :領域確保・描画 // /*==================================*/ boolean gamen1_InitAppData(fukusu2* poya) { char *fdata; gamen1 *pMe; AEERect rect; AECHAR *menubuf; char *menuTitle; //==========================================// // 領域確保 // //==========================================// pMe = (gamen1 *)MALLOC(sizeof(gamen1)); if (pMe == NULL ) { gamen1_FreeAppData(poya); return FALSE; } // アプリ領域へ設定 poya->garea = (void *)pMe; poya->gno = 1; pMe->pMenu1 = NULL; pMe->pIDisplay = poya->pIDisplay; pMe->pIShell = poya->pIShell; //==========================// // メニューの作成 // //==========================// if ( ISHELL_CreateInstance( pMe->pIShell, AEECLSID_MENUCTL, (void**)&pMe->pMenu1 ) != SUCCESS ) { gamen1_FreeAppData(poya); return FALSE; } rect.x = 1; rect.y = 1; rect.dx = 200; rect.dy = 150; IMENUCTL_SetRect(pMe->pMenu1,&rect); //==========================// // メニュー項目の表示 // //==========================// menuTitle = "開始"; menubuf = (AECHAR *)MALLOC((STRLEN(menuTitle)+1)*sizeof(AECHAR)); if ( menubuf == NULL ) { gamen1_FreeAppData(poya); return FALSE; } MEMSET(menubuf,0,(STRLEN(menuTitle)+1)*sizeof(AECHAR)); STREXPAND(menuTitle,STRLEN(menuTitle),menubuf, (STRLEN(menuTitle)+1)*sizeof(AECHAR)); IMENUCTL_AddItem(pMe->pMenu1,NULL,NULL,1000,menubuf,NULL); FREEIF(menubuf); menuTitle = "終了"; menubuf = (AECHAR *)MALLOC((STRLEN(menuTitle)+1)*sizeof(AECHAR)); if ( menubuf == NULL ) { gamen1_FreeAppData(poya); return FALSE; } MEMSET(menubuf,0,(STRLEN(menuTitle)+1)*sizeof(AECHAR)); STREXPAND(menuTitle,STRLEN(menuTitle),menubuf, (STRLEN(menuTitle)+1)*sizeof(AECHAR)); IMENUCTL_AddItem(pMe->pMenu1,NULL,NULL,2000,menubuf,NULL); FREEIF(menubuf); gamen1_DispAppData(pMe); // 共通領域を設定 // pMe->pMap = poya->pMap; return TRUE; } /*==================================*/ //関数名:gamen1_FreeAppData // //内容 :領域のフリー // /*==================================*/ void gamen1_FreeAppData(fukusu2* poya) { gamen1 *pMe; // 対象かどうかチェック if ( poya->gno != 1 ) return; if ( poya->garea == NULL ) return; pMe = (gamen1 *)poya->garea; // メニューフリー if ( pMe->pMenu1 != NULL ) { IMENUCTL_Release(pMe->pMenu1); pMe->pMenu1 = NULL; } FREEIF(pMe); // 親のエリアをクリア poya->garea = NULL; } /*==================================*/ // 関数名:gamen1_DispAppData // // 内容 :画面の初期表示 // /*==================================*/ boolean gamen1_DispAppData(gamen1* pMe) { int curpos,buhinpos; // 初期化 curpos = 0; buhinpos = 0; //==================================// // リドローする // //==================================// // ここに、 // 1.リドローと、 // 2.次のフォーカス指示を書く // テキストエリアのRedrawやUpdateする if ( pMe->pMenu1 != NULL ) { // リドロー IMENUCTL_Redraw(pMe->pMenu1); // カーソル番号pMe->curnoから、 // 部品の番号(仕様書のA桁のNo)に // 変換する。その番号をbuhinposだとすると if(buhinpos == 0) IMENUCTL_SetActive(pMe->pMenu1,TRUE); else IMENUCTL_SetActive(pMe->pMenu1,FALSE); } return TRUE; } |
(上記のプログラム中の< > ¥は、本当は半角です)
次回のこのシリーズは、3.雛形ソースです。