土木測量プログラムの開発 (メニュー表示)

2017/03/16


メニューの構成。

CASIO BASIC の MENU命令の様なメニューを作りたいと思います。

メニューの表示は文字数が少なく、表現がわかりやすい漢字表示にしたいと思います。

MENU 命令では枠線を使用するので 8 x 12 ドットの漢字表示は 4行までになります。 ただ、MENU 命令の様に上下にスクロールさせれば多くのメニュー表示が可能になります。

CASIO BASIC ではメニューの個数を任意に設定できましたが、動的な引数を使用したプログラムは自分には手におえないので、関数内でメニューの個数を指定したプログラムにします。

では、初めにアルゴリズムを考えます。


①前準備
  ・配列にメニュー文字を定義 [3]が無い場合でも空白でデータを作っておく
  ・変数を定義
    メニューの個数(max)   3~最大9個
    現在のメニュー番号(num) 初期値は引数より
    現在の選択行番号(sel)
    現在の一行目の表示番号(vw)

②枠表示
  ・画面の消去
  ・枠線の描画
  ・タイトルの描画

③初期変数
  ・メニュー番号
    if (num < 4) {
      vw = 0
      sel = num
    } else {
      vw = num - 3
      sel = 3
    }


④ループ
  A.表示
    ・表示範囲内消去
    ・配列 [vw] ~[vw+3] までの行を表示
    ・sel の行を反転表示
  B.キー入力
    ・一文字入力と各処理

一文字入力
  ・ファンクションキーの処理
  ・EXEファンクションキーの処理
  ・数値入力の処理
    inkey <= max return inkey
    else     何もしない
  ・上キーの処理
    if (sel != 0) {
      sel--
    } else if (vw != 0) {
      vw--
    }
  ・下キーの処理
    if (sel != 3) {
      sel++
    } else if ((sel + vw) != max) {
      vw++
    }

フォントデータと、上記のアルゴリズムをプログラムしたものが以下のものです。

なお、他に使用しそうなので矩形消去の関数を作っています。

// 漢字 8x12
static const unsigned char KanjiFont[][12] = {
     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 00 (SPC)
    ,{0x00, 0x00, 0x20, 0x62, 0x22, 0x20, 0x20, 0x22, 0x72, 0x00, 0x00, 0x00} // 01 1:
    ,{0x00, 0x00, 0x70, 0x8A, 0x0A, 0x10, 0x20, 0x42, 0xFA, 0x00, 0x00, 0x00} // 02 2:
    ,{0x00, 0x00, 0xF8, 0x12, 0x22, 0x10, 0x08, 0x8A, 0x72, 0x00, 0x00, 0x00} // 03 3:
    ,{0x00, 0x00, 0x10, 0x32, 0x52, 0x90, 0xF8, 0x12, 0x12, 0x00, 0x00, 0x00} // 04 4:
    ,{0x00, 0x00, 0xF8, 0x82, 0xF2, 0x08, 0x08, 0x8A, 0x72, 0x00, 0x00, 0x00} // 05 5:
    ,{0x00, 0x00, 0x30, 0x42, 0x82, 0xF0, 0x88, 0x8A, 0x72, 0x00, 0x00, 0x00} // 06 6:
    ,{0x00, 0x00, 0xF8, 0x0A, 0x12, 0x20, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00} // 07 7:
    ,{0x00, 0x00, 0x70, 0x8A, 0x8A, 0x70, 0x88, 0x8A, 0x72, 0x00, 0x00, 0x00} // 08 8:
    ,{0x00, 0x00, 0x70, 0x8A, 0x8A, 0x78, 0x08, 0x12, 0x62, 0x00, 0x00, 0x00} // 09 9:
    ,{0x00, 0x00, 0x70, 0x8A, 0x9A, 0xA8, 0xC8, 0x8A, 0x72, 0x00, 0x00, 0x00} // 0A 0:
    ,{0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x00} // 0B (
    ,{0x80, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x80, 0x00} // 0C )
    ,{0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00} // 0D :
    ,{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 0E (SPC)
    ,{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 0F (SPC)
    ,{0xE4, 0x04, 0xE4, 0x04, 0xFE, 0x04, 0xE4, 0x04, 0xE4, 0xA4, 0xE4, 0x00} // 10 計
    ,{0x48, 0x6E, 0xB4, 0x7C, 0x44, 0x7C, 0x44, 0x7C, 0x28, 0xFE, 0x48, 0x00} // 11 算
    ,{0xBA, 0x2A, 0x3E, 0xAE, 0x3E, 0x2E, 0x2A, 0xBA, 0x82, 0xAA, 0xAA, 0x00} // 12 測
    ,{0x7C, 0x44, 0x7C, 0x44, 0xFE, 0x54, 0x7C, 0x54, 0x7C, 0x10, 0xFE, 0x00} // 13 量
    ,{0x08, 0x7E, 0x54, 0x54, 0x54, 0x6A, 0x48, 0x5C, 0x48, 0x48, 0xBE, 0x00} // 14 座
    ,{0x7E, 0x54, 0xFE, 0x7E, 0x40, 0xDC, 0xC0, 0xFE, 0x48, 0x6A, 0x58, 0x00} // 15 標
    ,{0xEE, 0xAA, 0xEE, 0x10, 0xFE, 0x28, 0xC6, 0x00, 0xEE, 0xAA, 0xEE, 0x00} // 16 器
    ,{0x4A, 0x48, 0xFE, 0x44, 0x54, 0xFC, 0xD6, 0xD4, 0x64, 0x4A, 0x52, 0x00} // 17 械
    ,{0x10, 0x10, 0x1C, 0x10, 0x7C, 0x44, 0x44, 0x7C, 0x00, 0x54, 0xAA, 0x00} // 18 点
    ,{0x5E, 0x40, 0xDE, 0xD2, 0xDE, 0xC0, 0xFE, 0x6A, 0x7E, 0x6A, 0x7E, 0x00} // 19 幅
    ,{0x40, 0x7E, 0x52, 0x92, 0x12, 0x22, 0x22, 0x4A, 0x76, 0x02, 0x0C, 0x00} // 1A 勾
    ,{0xEE, 0x42, 0x42, 0xE2, 0xEE, 0xE8, 0xA8, 0xA8, 0xEA, 0xAA, 0xEE, 0x00} // 1B 配
    ,{0x5A, 0x52, 0xA0, 0xCE, 0x54, 0xB4, 0xD4, 0x56, 0xD4, 0x5C, 0x56, 0x00} // 1C 縦
    ,{0x54, 0x7E, 0xD4, 0x7E, 0x48, 0xFE, 0xEA, 0xFE, 0x40, 0x54, 0x62, 0x00} // 1D 横
    ,{0xA2, 0xEC, 0xF8, 0xA8, 0xFE, 0xAA, 0xFA, 0xEA, 0xAA, 0x8A, 0xF2, 0x00} // 1E 断
    ,{0xE8, 0xAE, 0xAA, 0xF4, 0x44, 0x4A, 0xF0, 0xCE, 0xCA, 0xEA, 0xCE, 0x00} // 1F 路
    ,{0x48, 0x5C, 0x94, 0xDC, 0x54, 0x9C, 0xC8, 0x7A, 0xDC, 0x6A, 0x58, 0x00} // 20 線
    ,{0xFA, 0x52, 0x54, 0x50, 0xFA, 0x52, 0x54, 0x50, 0x52, 0x52, 0x94, 0x00} // 21 形
    ,{0x10, 0x10, 0xFE, 0x20, 0x20, 0x3C, 0x48, 0x48, 0x88, 0x08, 0x7E, 0x00} // 22 左
    ,{0x10, 0x10, 0xFE, 0x20, 0x20, 0x3C, 0x64, 0xA4, 0x24, 0x24, 0x3C, 0x00} // 23 右
    ,{0xFE, 0xAA, 0xEA, 0xAA, 0xAA, 0xFE, 0x84, 0xAC, 0xAC, 0xEC, 0x16, 0x00} // 24 既
    ,{0x40, 0x4E, 0x7A, 0xAA, 0x2A, 0xFA, 0x2A, 0x2A, 0x5A, 0x5A, 0x8E, 0x00} // 25 知
    ,{0x24, 0x38, 0x48, 0x48, 0xC8, 0x7E, 0x48, 0x48, 0x48, 0x48, 0x5C, 0x00} // 26 任
    ,{0x10, 0x7C, 0x28, 0xFE, 0x44, 0x7C, 0x44, 0x7C, 0x50, 0xCA, 0xBA, 0x00} // 27 意
    ,{0xFE, 0x28, 0xFE, 0xAA, 0xFE, 0x10, 0xFE, 0x24, 0x68, 0x18, 0xE6, 0x00} // 28 要
    ,{0x10, 0x7C, 0x10, 0x7C, 0x10, 0xFE, 0x50, 0x24, 0xFE, 0x54, 0x92, 0x00} // 29 素
    ,{0x10, 0xFE, 0x44, 0x7C, 0x00, 0xFE, 0x82, 0xBA, 0xAA, 0xBA, 0x86, 0x00} // 2A 高
    ,{0x74, 0xAA, 0x44, 0xBA, 0x00, 0x7C, 0x44, 0x7C, 0x28, 0x28, 0xFE, 0x00} // 2B 登
    ,{0x5C, 0xA4, 0x1C, 0xC4, 0x7E, 0xC8, 0x6A, 0xDC, 0xEA, 0x48, 0xD8, 0x00} // 2C 録
    ,{0x00, 0x7C, 0x10, 0x20, 0xFE, 0x10, 0x20, 0x20, 0x20, 0x1C, 0x00, 0x00} // 2D そ
    ,{0x00, 0x00, 0x38, 0x54, 0x92, 0x92, 0xA2, 0xA2, 0x44, 0x18, 0x00, 0x00} // 2E の
    ,{0x24, 0x34, 0x56, 0x5E, 0xF6, 0x56, 0x54, 0x54, 0x52, 0x52, 0x5E, 0x00} // 2F 他
    ,{0x10, 0xFE, 0x28, 0xAA, 0xAA, 0x40, 0x38, 0x68, 0x10, 0x28, 0xC6, 0x00} // 30 変
    ,{0x4C, 0x54, 0xC4, 0x7E, 0x6A, 0x76, 0xE2, 0x7E, 0x48, 0x54, 0xE2, 0x00} // 31 換
    ,{0x44, 0x5E, 0xD0, 0x54, 0x54, 0x54, 0xD4, 0x68, 0x4A, 0x52, 0xDE, 0x00} // 32 拡
    ,{0xFE, 0x00, 0x7E, 0x42, 0x7E, 0x48, 0x7E, 0x48, 0x48, 0x54, 0xA2, 0x00} // 33 戻
    ,{0x00, 0x7C, 0x08, 0x10, 0x38, 0x44, 0x82, 0x32, 0x4C, 0x38, 0x00, 0x00} // 34 る
};
// 矩形消去
ClearBox(int x1, int y1, int x2, int y2) {
    DISPBOX ClrBox;  // 構造体の定義
    ClrBox.left = x1;
    ClrBox.top = y1;
    ClrBox.right = x2;
    ClrBox.bottom = y2;

    Bdisp_AreaClr_DDVRAM(&ClrBox);  // 消去 
}

// メニュー
int Menu(int i) {
    char max = 5; // メニューの最大値
    char sel;     // 選択されている行番号
    char vw;      // 0行に表示されるメニュー番号
    char key;     // 一文字取得に使用
    int ret;      // 戻り値に使用

// 文字列定義
    char MenuTxt[6][11] = {
         {0x01, 0x0F, 0x16, 0x17, 0x18, 0x2B, 0x2C, 0x0F, 0x0F, 0x0F, 0x00} //器械点登録
        ,{0x02, 0x0F, 0x14, 0x15, 0x30, 0x31, 0x28, 0x29, 0x2B, 0x2C, 0x00} //座標変換要素登録
        ,{0x03, 0x0F, 0x20, 0x21, 0x28, 0x29, 0x2B, 0x2C, 0x0F, 0x0F, 0x00} //線形要素登録
        ,{0x04, 0x0F, 0x1C, 0x1E, 0x28, 0x29, 0x2B, 0x2C, 0x0F, 0x0F, 0x00} //縦断要素登録
        ,{0x05, 0x0F, 0x32, 0x19, 0x28, 0x29, 0x2B, 0x2C, 0x0F, 0x0F, 0x00} //拡幅要素登録
        ,{0x06, 0x0F, 0x1D, 0x1E, 0x28, 0x29, 0x2B, 0x2C, 0x0F, 0x0F, 0x00} //横断勾配登録
    };

    FuncKey = 0;  // ファンクションキー用の変数
// 枠線
    Bdisp_DrawLineVRAM(  0,  0, 126,  0); // 線(上)
    Bdisp_DrawLineVRAM(  0, 62, 126, 62); // 線(下)
    Bdisp_DrawLineVRAM(  0,  0,   0, 62); // 線(左)
    Bdisp_DrawLineVRAM(126,  0, 126, 62); // 線(右)
    Bdisp_DrawLineVRAM(  0, 10, 126, 10); // 線(中)
    Bdisp_DrawLineVRAM(127,  1, 127, 62); // 線(影右)
    Bdisp_DrawLineVRAM(  1, 63, 127, 63); // 線(影下)
    CPrint(4, 1, (char*)"F1:Setup Menu", 3, 2); // タイトル文字

// 初期値を代入
    if (i < 4) {
        vw = 0;
        sel = i;
    } else {
        vw = i - 3;
        sel = 3;
    }

// ループ
    while(1) {
// メニュー表示
        ClearBox(3, 13 ,125, 61);               // 消去
        KPrint(4, 13, (char*)&MenuTxt[vw]);     // 1行目メニュー文字列
        KPrint(4, 25, (char*)&MenuTxt[vw + 1]); // 2行目
        KPrint(4, 37, (char*)&MenuTxt[vw + 2]); // 3行目
        KPrint(4, 49, (char*)&MenuTxt[vw + 3]); // 4行目
        Bdisp_AreaReverseVRAM(3, sel * 12 + 13, 123, sel * 12 + 24); // 選択行を反転

        key = GetOneKey();  // 一文字取得
        switch (key) {
            case 'a':  // F1
            case 'b':  // F2
            case 'd':  // F4
                FuncKey = key - 0x60;
                ret = i;
                return ret;
                break;
            case 'E':  // EXE
                ret = vw + sel + 1;
                return ret;
                break;
            case 'U':  // UP
                if (sel != 0) {
                    sel--;
                } else if (vw != 0) {
                    vw--;
                }
                break;
            case 'W':  // DOWN
                if (sel != 3) {
                    sel++;
                } else if ((sel + vw) != max) {
                    vw++;
                }
                break;
            case '1':  // 1
            case '2':  // 2
            case '3':  // 3
            case '4':  // 4
            case '5':  // 5
            case '6':  // 6
            case '7':  // 7
            case '8':  // 8
            case '9':  // 9
                if ((key - 0x30) < max + 2) {
                    ret = key - 0x30;
                    return ret; 
                }
                break;
            default:
                break;
        }
    }
}

汎用メニューに修正

F1 を押したときと F2 を押したときでは異なるメニューが表示されるように修正します。

引数にモードを加え、2種類のメニューを表示するようにします。 文字配列の 0~9 が F1 メニュー、 10~19 が F2 メニューの文字列となります。

引数と変数・配列の定義部分を修正します。

// メニュー
int Menu(int i, char mode) {  // 引数に mode を追加
    char max;  // 条件式で値を代入するので定義のみ
    char sel;
    char vw;
    char key;
    int ret;

// 文字列定義  全文字列を定義
    char MenuTxt[20][11] = {
         {0x01, 0x0F, 0x16, 0x17, 0x18, 0x2B, 0x2C, 0x0F, 0x0F, 0x0F, 0x00} //器械点登録
        ,{0x02, 0x0F, 0x14, 0x15, 0x30, 0x31, 0x28, 0x29, 0x2B, 0x2C, 0x00} //座標変換要素登録
        ,{0x03, 0x0F, 0x20, 0x21, 0x28, 0x29, 0x2B, 0x2C, 0x0F, 0x0F, 0x00} //線形要素登録
        ,{0x04, 0x0F, 0x1C, 0x1E, 0x28, 0x29, 0x2B, 0x2C, 0x0F, 0x0F, 0x00} //縦断要素登録
        ,{0x05, 0x0F, 0x32, 0x19, 0x28, 0x29, 0x2B, 0x2C, 0x0F, 0x0F, 0x00} //拡幅要素登録
        ,{0x06, 0x0F, 0x1D, 0x1E, 0x28, 0x29, 0x2B, 0x2C, 0x0F, 0x0F, 0x00} //横断勾配登録
        ,{0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x08, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x09, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x0A, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x01, 0x0F, 0x14, 0x15, 0x10, 0x11, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //座標計算
        ,{0x02, 0x0F, 0x20, 0x21, 0x10, 0x11, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //線形計算
        ,{0x03, 0x0F, 0x1F, 0x20, 0x10, 0x11, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //路線計算 ,{0x04, 0x0F, 0x1C, 0x1E, 0x28, 0x29, 0x2B, 0x2C, 0x0F, 0x0F, 0x00} //縦断要素登録
        ,{0x04, 0x0F, 0x2D, 0x2E, 0x2F, 0x2E, 0x10, 0x11, 0x0F, 0x0F, 0x00} //その他の計算
        ,{0x05, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x06, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x08, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x09, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x0A, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
    };

    FuncKey = 0;
// 枠線
    Bdisp_DrawLineVRAM(  0,  0, 126,  0);
    Bdisp_DrawLineVRAM(  0, 62, 126, 62);
    Bdisp_DrawLineVRAM(  0,  0,   0, 62);
    Bdisp_DrawLineVRAM(126,  0, 126, 62);
    Bdisp_DrawLineVRAM(  0, 10, 126, 10);
    Bdisp_DrawLineVRAM(127,  1, 127, 62);
    Bdisp_DrawLineVRAM(  1, 63, 127, 63);

// モード別に変数を定義
    if (mode == 0) {
        max = 5;
        CPrint(4, 1, (char*)"F1:Setup Menu", 3, 2);
    } else {
        mode = 10;
        max = 3;
        CPrint(4, 1, (char*)"F2:Calc Menu", 3, 2);
    }

ループ内の文字表示部分を修正します。

// ループ
    while(1) {
// メニュー表示
        ClearBox(3, 13 ,125, 61);
        KPrint(4, 13, (char*)&MenuTxt[mode + vw]);     // mode を加算して表示
        KPrint(4, 25, (char*)&MenuTxt[mode + vw + 1]);
        KPrint(4, 37, (char*)&MenuTxt[mode + vw + 2]);
        KPrint(4, 49, (char*)&MenuTxt[mode + vw + 3]);
        Bdisp_AreaReverseVRAM(3, sel * 12 + 13, 123, sel * 12 + 24);

補助メニューを作成

拡幅や横断勾配を選択したのちに右か左の選択をしたいのでサブメニューを作ります。

サブメニューでは 0 番を戻るに固定し、2 か 3 つの選択しか許可しません。 よって、画面のスクロールは出来ません。 また、サブメニューでは初期値の引数はありません。 初期値は 0 固定です。

サブメニューの表示は、呼び出し元のメインメニューの表示を残したまま行います。

サブメニューでも複数のモードを選択できるようにします。

int SubMenu(char mode) {
    int ret = 0;
    char MenuTxt[12][8] = {
         {0x0A, 0x0F, 0x33, 0x34, 0x0F, 0x0F, 0x0F, 0x00} //戻る
        ,{0x01, 0x0F, 0x24, 0x25, 0x18, 0x0F, 0x0F, 0x00} //既知点
        ,{0x02, 0x0F, 0x26, 0x27, 0x18, 0x0F, 0x0F, 0x00} //任意点
        ,{0x03, 0x0F, 0x16, 0x17, 0x2A, 0x0F, 0x0F, 0x00} //器械高
        ,{0x0A, 0x0F, 0x33, 0x34, 0x0F, 0x0F, 0x0F, 0x00} //戻る
        ,{0x01, 0x0F, 0x32, 0x19, 0x0B, 0x22, 0x0C, 0x00} //拡幅(左)
        ,{0x02, 0x0F, 0x32, 0x19, 0x0B, 0x23, 0x0C, 0x00} //拡幅(右)
        ,{0x03, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x0A, 0x0F, 0x33, 0x34, 0x0F, 0x0F, 0x0F, 0x00} //戻る
        ,{0x01, 0x0F, 0x1A, 0x1B, 0x0B, 0x22, 0x0C, 0x00} //勾配(左)
        ,{0x02, 0x0F, 0x1A, 0x1B, 0x0B, 0x23, 0x0C, 0x00} //勾配(右)
        ,{0x03, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
    };

    ClearBox(34, 7 ,98, 57);            // 消去
    Bdisp_DrawLineVRAM(34,  7, 98,  7); // 線(上)
    Bdisp_DrawLineVRAM(34, 57, 98, 57); // 線(下)
    Bdisp_DrawLineVRAM(34,  7, 34, 57); // 線(左)
    Bdisp_DrawLineVRAM(98,  7, 98, 57); // 線(右)
    Bdisp_DrawLineVRAM(99,  8, 99, 58); // 線(影右)
    Bdisp_DrawLineVRAM(35, 58, 99, 58); // 線(影下)
    KPrint(36,  9, (char*)&MenuTxt[mode * 4]);     // 1行目メニュー文字列
    KPrint(36, 21, (char*)&MenuTxt[mode * 4 + 1]); // 2行目
    KPrint(36, 33, (char*)&MenuTxt[mode * 4 + 2]); // 3行目
    KPrint(36, 45, (char*)&MenuTxt[mode * 4 + 3]); // 4行目
    Bdisp_AreaReverseVRAM(36, 9, 92, 19); // 選択行を反転
}



// サブメニュー
int SubMenu(char mode) {
    int ret = 0;
    int sel = 0;
    int key;

    char MenuTxt[12][8] = {
         {0x0A, 0x0F, 0x33, 0x34, 0x0F, 0x0F, 0x0F, 0x00} // 戻る
        ,{0x01, 0x0F, 0x24, 0x25, 0x18, 0x0F, 0x0F, 0x00} // 既知点
        ,{0x02, 0x0F, 0x26, 0x27, 0x18, 0x0F, 0x0F, 0x00} // 任意点
        ,{0x03, 0x0F, 0x16, 0x17, 0x2A, 0x0F, 0x0F, 0x00} // 器械高
        ,{0x0A, 0x0F, 0x33, 0x34, 0x0F, 0x0F, 0x0F, 0x00} // 戻る
        ,{0x01, 0x0F, 0x32, 0x19, 0x0B, 0x22, 0x0C, 0x00} // 拡幅(左)
        ,{0x02, 0x0F, 0x32, 0x19, 0x0B, 0x23, 0x0C, 0x00} // 拡幅(右)
        ,{0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
        ,{0x0A, 0x0F, 0x33, 0x34, 0x0F, 0x0F, 0x0F, 0x00} // 戻る
        ,{0x01, 0x0F, 0x1A, 0x1B, 0x0B, 0x22, 0x0C, 0x00} // 勾配(左)
        ,{0x02, 0x0F, 0x1A, 0x1B, 0x0B, 0x23, 0x0C, 0x00} // 勾配(右)
        ,{0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00} //
    };

    FuncKey = 0;
// 枠線
    ClearBox(32, 7 ,96, 57);            // 消去
    Bdisp_DrawLineVRAM(32,  7, 96,  7); // 枠線(上)
    Bdisp_DrawLineVRAM(32, 57, 96, 57); // 枠線(下)
    Bdisp_DrawLineVRAM(32,  7, 32, 57); // 枠線(左)
    Bdisp_DrawLineVRAM(96,  7, 96, 57); // 枠線(右)
    Bdisp_DrawLineVRAM(97,  8, 97, 58); // 枠線(影右)
    Bdisp_DrawLineVRAM(33, 58, 97, 58); // 枠線(影下)

// ループ
    while(1) {
        ClearBox(33, 8 ,95, 56);
        KPrint(36, 9, (char*)&MenuTxt[mode * 4]);      // 1行目表示
        KPrint(36, 21, (char*)&MenuTxt[mode * 4 + 1]); // 2行目表示
        KPrint(36, 33, (char*)&MenuTxt[mode * 4 + 2]); // 3行目表示
        KPrint(36, 45, (char*)&MenuTxt[mode * 4 + 3]); // 4行目表示
        Bdisp_AreaReverseVRAM(35, sel * 12 + 9, 93, sel * 12 + 19); // 選択行反転

        key = GetOneKey(); // 一文字入力
        switch (key) {
            case 'U': // 上キー
                sel--;
                break;
            case 'W': // 下キー
                sel++;
                break;
            case 'E': // EXEキー
                return sel;
                break;
            case '3': // 番号行の実行
                if(MenuTxt[mode * 4 + sel][0] == 0x0F) break; // 4行目が空白なら何もしない
            case '0':
            case '1':
            case '2':
                ret = key - 0x30;
                return ret;
                break;
        }

// 選択行の判定
        if(sel < 0) sel = 0;
        if(sel > 3) sel = 3;
        if(MenuTxt[mode * 4 + sel][0] == 0x0F) sel--;
    }
}