前回でコードについては全て書きましたので、今回は「実際に使ってみるとどうか」、なんて書いてみましょう。

 

何度も表示していますが、単に起動すると

 

こんな風になります。又起動時に「実行リスト実行命令のファイル - *.tge)」をドロップするとそれが読み込まれ、又起動してからドロップしても同様に読み込まれます。「読み込まれているかどうか」の違いはウィンドウ最下部のステータスバーに表示されるファイル名で分かります。

(解説:   ↑ここです。)

 

ここで「ファイル」-「実行ファイルの新規作成」をメニューやツールバーボタンで選択すると、

 

と確認が出ます。要すれば「ファイル」メニューの対象ファイルは実行リスト(TGEクラスインスタンスのtge.ExeListメンバー)であり、「新規作成」はその初期化だけの意味しかありません。この確認に対して「はい」と答えると、(既にファイルがあってもなくても)次のダイアログが「何をすればよいのか(ToDo)」の操作指示を表示します。(尚、既にファイルを読み込んでいた場合には初期化され「(ファイル名)」状態に戻ります。)

 

例えば↑の第2パラにある「命令リスト(ダイアログ)」の「命令追加(ボタン)」から「(「命令入力ダイアログ」をつかって)命令セット」を作ります。この操作は画像を含めにやりましたね?(その結果、PenColor命令入力の仕様変更も行いました。)

又、作成した「命令セット(TGSetクラスインスタンス)」はダイアログを「はい」で終了すると自動的に「命令リスト(「命令セットライブラリー」であるTGEクラスインスタンスのtge.CmdListメンバー)」に追加されるので、即座に「実行」-「命令セットの実行」メニュー(またはツールバーの緑色の横▲ボタン)で命令セットライブラリー」から選択して実行できます。

 

単体の描画「命令セット」は部品として命令セットライブラリー」に登録されるので、

 

それを好きなように選択し、実行リスト(TGEクラスインスタンスのtge.ExeListメンバー)」に登録することができ、やや複雑な画像を連続して描画することが可能です。

 

又それらを「名前を付けて保存」することで、その後に「ファイル」ー「実行ファイルを開く」で読み込んで、「編集]-「実行リスト編集」で追加、削除、編集して新しい「実行リストファイルにすることができ、画像作成の生産効率が向上します。

(解説:最後の2枚は↑で単体で描いた命令セットのPenColor命令と繰り返し回数を変化させたものです。)

 

このような訳で、最初にやったダイアログへの描画命令記述()はWYSWYG化と再利用化が可能となりました

【TurtleGraphics】TurtleGraphics01

  【TurtleGraphics】TurtleGraphics02

  【TurtleGraphics】TurtleGraphics03

 

が、一方

 

独特な関数を用いた描画や、繰り返しネスティングの複雑な描画等には対応できないという限界も明確になりました。でも、それは「わかった上での設計方針」であったし、それを基に仕様を決めたのだから

 

No problem/No worries

没問題(メイウェンティ)

 

なんですが、矢張り対応できないのもちょっと気になるので、

 

なんくるナイサー

 

ということで、最初に作ったダイアログを使って

 

「独特な関数を用いた描画や、繰り返しネスティングの複雑な描画等はこっちを使いましょう。」

 

ということにしました。それはまた次回。

 

前回からの続きです。

 

【TGEditor.cs】

続き

        //終了処理
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            DialogResult dr = MessageBox.Show("終了しますか?", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if(dr == DialogResult.No)
            {
                e.Cancel = true;
            }
            //命令セットライブラリー(CmdList.tge)を書き込む(解説:一応システム管理です。上書きではなく、日時を付けて別ファイル処理の方がより安全ですが...)
            tge.CmdList.FileName = ".\\tgeFiles\\CmdList.tge";
            tge.CmdList.WriteFile();
        }

        //「新規作成」処理(解説:実際は「初期化」処理ですね。)
        private void OnNew_Click(object sender, EventArgs e)
        {
            if(tssl[1].Text != "(ファイル名)")
            {
                DialogResult dr = MessageBox.Show("データがありますが、初期化しますか?", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if(dr == DialogResult.Yes)
                {
                    tssl[1].Text = "(ファイル名)";
                    tssl[1].ToolTipText = "(ファイル名)";        //ToolTip設定
                }
                else
                    return;
            }
            tge.Reset();            //Nakov.TurtleGraphics初期化
            tge.ExeList.Clear();    //「実行リスト(ExeList)」初期化
            MessageBox.Show("実行リストを作るには、「実行リストの編集」で「命令リスト」から「命令セット」を選んでください。\r\n" +
                            "「命令リスト」は「命令リスト編集」で編集できます。また、新たに命令セットを作成するには「命令セット" +
                            "作成」または「命令リスト編集」の「命令セット追加」を選んでください。", "ToDo", MessageBoxButtons.OK,
                            MessageBoxIcon.Information);
        }

        //「ファイルを開く」処理
        private void OnOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofDlg = new OpenFileDialog();
            //ファイルフィルターの指定
            ofDlg.Filter = "タートルグラフィックデータファイル|*.tge";
            ofDlg.FilterIndex = 0;
            ofDlg.RestoreDirectory = true;    //初期ディレクトリへ復帰
            ofDlg.CheckPathExists = true;    //ファイルパスの存在チェック
            ofDlg.InitialDirectory = ".\\tgeFiles";            // デフォルトのフォルダーの指定
            ofDlg.Title = "ファイルを開く";    //ダイアログのタイトルを指定する
            if(ofDlg.ShowDialog() == DialogResult.Cancel)    //ダイアログを表示する
            {
                MessageBox.Show("キャンセルされました。", "キャンセル", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else
            {
                if(Path.GetExtension(ofDlg.FileName) == ".tge")
                {
                    tssl[1].Text = ofDlg.FileName;            //ファイル名を記録
                    tssl[1].ToolTipText = ofDlg.FileName;    //ToolTip設定
                    //ExeListを初期化、ファイル読み込み(解説:対象は実行リストファイルです。)
                    tge.ExeList.Clear();
                    tge.ExeList.FileName = tssl[1].Text;
                    tge.ExeList.ReadFile();
                }
                else
                {
                    //エラー処理
                    MessageBox.Show("タートルグラフィックデータファイル(*.tge)ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            //オブジェクトを破棄する
            ofDlg.Dispose();
        }

        //「保存」処理
        private void OnSave_Click(object sender, EventArgs e)
        {
            if(tssl[1].Text == "(ファイル名)")
                OnSaveAs_Click(sender, e);
            else
            {
                //ファイル保存処理
                tge.ExeList.FileName = tssl[1].Text;
                tge.ExeList.WriteFile();
            }
        }

        //「名前を付けて保存」処理
        private void OnSaveAs_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfDlg = new SaveFileDialog();
            //ファイルフィルターの指定
            sfDlg.AddExtension = true;        //拡張子自動付加
            sfDlg.DefaultExt = ".tge";
            sfDlg.Filter = "タートルグラフィックデータファイル|*.tge";
            sfDlg.FilterIndex = 0;
            sfDlg.RestoreDirectory = true;    //初期ディレクトリへ復帰
            sfDlg.CheckPathExists = true;    //ファイルパスの存在チェック
            sfDlg.InitialDirectory = ".\\tgeFiles";            // デフォルトのフォルダーの指定
            sfDlg.Title = "ファイルを保存";    //ダイアログのタイトルを指定する
            sfDlg.OverwritePrompt = true;    //上書き確認
            if(sfDlg.ShowDialog() == DialogResult.Cancel)    //ダイアログを表示する
            {
                MessageBox.Show("キャンセルされました。", "キャンセル", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else
            {
                //ファイル名を記録
                tssl[1].Text = sfDlg.FileName;
                tssl[1].ToolTipText = sfDlg.FileName;    //ToolTip設定
                //ファイル保存処理
                tge.ExeList.FileName = tssl[1].Text;
                tge.ExeList.WriteFile();
            }
            //オブジェクトを破棄する
            sfDlg.Dispose();
        }

        //「終了」処理
        private void OnExit_Click(object sender, EventArgs e)
        {
            Close();    //修了確認はOnClosingメソッドで行う
        }

        //「命令セット作成」処理
        private void OnSetEdit_Click(object sender, EventArgs e)
        {
            //CmdSetDlgによる命令セットの作成
            CmdSetDlg csd = new CmdSetDlg();    //引数無し(新規作成)
            if(csd.ShowDialog(this) == DialogResult.OK)
            {
                tge.CmdList.AddSet(csd.Tgs);    //作成したTGSetはCmdListに追加する
            }
            csd.Dispose();
        }

        //「命令リスト編集」処理
        private void OnListEdit_Click(object sender, EventArgs e)
        {
            //CmdListDlgによる命令セットの編集
            CmdListDlg cld = new CmdListDlg(tge, 1);
            if(cld.ShowDialog(this) == DialogResult.OK)
            {
                MessageBox.Show("命令リストが編集されました", "確認", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            cld.Dispose();
        }

        //「実行リスト編集」処理
        private void OnExeListEdit_Click(object sender, EventArgs e)
        {
            //CmdListDlgによる命令セットの編集
            CmdListDlg cld = new CmdListDlg(tge, 2);
            if(cld.ShowDialog(this) == DialogResult.OK)
            {
                MessageBox.Show("実行リストが編集されました", "確認", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            cld.Dispose();
        }

        //「命令セット実行」処理
        private void OnSetExe_Click(object sender, EventArgs e)
        {
            //CmdListDlgによる命令セットの選択
            CmdListDlg cld = new CmdListDlg(tge, 0);
            if(cld.ShowDialog(this) == DialogResult.OK)
            {
                //描画初期化
                tge.Reset();
                tge.CmdList.GetSet(cld.Selection).DoThis();
            }
            cld.Dispose();
        }

        //「実行リスト実行」処理
        private void OnExe_List_Click(object sender, EventArgs e)
        {
            //描画初期化
            tge.Reset();
            tge.ExeList.DoSet();
        }

        //「使い方」処理(解説:本当はもっと素敵な表示にしたかったのですが...手抜きでした。)
        private void OnHowtoUse_Click(object sender, EventArgs e)
        {
            MessageBox.Show("TGEditorはNakov.TurtleGraphics用の描画エディターです。\r\n\r\n" +
            "LOGOベースの描画命令を纏めた「命令セット」、その一覧である「命令リスト」及び" +
            "指定する「命令セット」で繰り返しを含め実行順を定めた「実行リスト」を編集し、" +
            "「命令セット」単体や「実行リスト」を実行してウィンドウに描画します。\r\n\r\n" +
            "出来上がった「命令リスト」、「実行リスト」は\"*.tge\"ファイルにすることができ" +
            "\"*.tge\"ファイルで起動したり、また起動後もドラッグアンドドロップすることができます。\r\n\r\n" +
            "【TurtleGraphicsメソッド】\r\n" +
            "Init(arg)-タートルグラフィックスシステムを初期化します。argは描画対象のFormsコントロールで、指定しない場合、アクティブなフォームが描画領域となります。\r\n" +
            "Dispose() / Reset()-タートルグラフィックスシステムを破棄し、関連するすべてのリソースを解放します。\r\n" +
            "Forward(arg)-現在の方向に亀をarg1ピクセル前進させ、ペンが下がっている場合線を描きます。\r\n" +
            "Backward(arg)-現在の方向に亀をarg1ピクセル後退させ、ペンが下がっている場合線を描きます。\r\n" +
            "MoveTo(arg1, arg2)-亀を指定した位置へ移動させます。ペンが下がっている場合線を描きます。\r\n" +
            "Rotate(arg)-現在の向きからarg(度数)亀を回転させます。\r\n" +
            "RotateTo(arg)-亀を指定角度(度数)へ向けます。初期状態の亀の方向(角度)は0度(上向き)です。\r\n" +
            "PenUp()-ペンを描画面から離し、線は描かれません。\r\n" +
            "PenDown()-ペンを描画面に降ろし、線が描かれます。\r\n\r\n" +
            "【TurtleGraphicsプロパティ】\r\n" +
            "X-亀の現在X座標を取得/設定します。初期状態の亀は {0, 0}(画面中央)です。\r\n" +
            "Y-亀の現在Y座標を取得/設定します。初期状態の亀は {0, 0}(画面中央)です。\r\n" +
            "Angle-亀の現在方向(度数)を取得/設定します。(上-0、右-90、下-180、左-270)\r\n" +
            "PenColor-描画色を取得/設定します。既定色はBlue(青)です。\r\n" +
            "PenSize-描画太さ(ピクセル単位)を取得/設定します。規定値は7です。\r\n" +
            "PenVisible-ペンが下がり描画可能であればtrue、ペンが上がればfalseとなります。\r\n" +
            "ShowTurtle-亀の表示可否を取得/設定します。規定値は表示可です。\r\n" +
            "Delay-移動/回転後の待機時間(ミリ秒)を取得/設定します。規定値は0です。",
            "簡単な説明", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        //「ショートカットキー」処理
        private void OnShortcutKey_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Ctrl+N-新規作成\r\nCtrl+O-ファイルを開く\r\n" +
            "Ctrl+S-ファイルの保存\r\nCtrl+P-印刷\r\nCtrl+X-終了\r\n\r\n" +
            "Ctrl+T-命令セット編集\r\nCtrl+L-命令リスト編集\r\nCtrl+E-実行リスト編集\r\n\r\n" +
            "Ctrl+H-使い方\r\nF1-ショートカットキーの解説\r\nF2-バージョン情報",
            "ショートカットキーの解説", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        //「バージョン」処理
        private void OnVersion_Click(object sender, EventArgs e)
        {
            VersionDlg verDlg = new VersionDlg(this.Icon);    //Versionダイアログ表示
            verDlg.ShowDialog();
            verDlg.Dispose();
        }
    }

    /////////////////////
    //Version ダイアログ
    /////////////////////

    class VersionDlg : Form
    {
        public VersionDlg(Icon ico)
        {
            //ダイアログの属性設定
            this.Text = "バーション情報";
            this.ClientSize = new Size(320, 100);
            this.MaximizeBox = false;        // 最大化ボタン
            this.MinimizeBox = false;        // 最小化ボタン
            this.ShowInTaskbar = false;        //タスクバー上表示
            this.FormBorderStyle = FormBorderStyle.FixedDialog;        // 境界のスタイル
            this.StartPosition = FormStartPosition.CenterParent;    // 親フォームの中央に配置
            //コントロールの属性設定
            Button btnOK = new Button();
            btnOK.Size = new Size(40, 28);
            btnOK.Location = new Point(ClientSize.Width - btnOK.Width - 10, (ClientSize.Height - btnOK.Height) / 2);
            btnOK.Text = "OK";
            btnOK.Click += new EventHandler(OnOK_Click);
            Label imglabel = new Label();
            imglabel.Size = new Size(40, 40);
            imglabel.Location = new Point(10, (ClientSize.Height - imglabel.Height) / 2);
            imglabel.BorderStyle = BorderStyle.Fixed3D;
            imglabel.Image = ico.ToBitmap();                        //親のシステムアイコン
            Label label = new Label();
            label.Size = new Size(ClientSize.Width - imglabel.Width - btnOK.Width - 40, ClientSize.Height- 20);
            label.Location = new Point(imglabel.Width + 20, (ClientSize.Height - label.Height) / 2);
            label.BorderStyle = BorderStyle.Fixed3D;
            label.Text = "TGEditor Version 1.0\r\nCopyright (c) 2026 by Ysama\r\n(written in Microsoft C#)";
            label.TextAlign = ContentAlignment.MiddleCenter;
            label.Font = new Font("Times New Roman", 10, FontStyle.Bold);
            this.Controls.Add(btnOK);
            this.Controls.Add(imglabel);
            this.Controls.Add(label);
        }

        private void OnOK_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}
 

はー、しんど。

 

書く方も大変です。次回からは(絵心のない私ですが)少し使い方をやってみましょうか?

 

さーて、前回で書いた通り、最後の「器プログラム」でプログラムの解説を終了します。今後は自分で使ってみた印象や改良点(てか、もうまた仕様変更しちゃったのですが...テヘ)と番外編が続きます。(尚、また字数制限に引っかかったので分割します。)

 

【TGEditor.cs】

///////////////////////////////
//        TGEditor.cs
// Copyright (c) 2026 by ysama
///////////////////////////////

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;                //Assemblyを使う為
using System.Resources;                    //リソース関係クラス等の使用の為
using System.IO;                        //File.ReadAllText使用の為
using System.Text;                        //Encoding.GetEncoding使用の為
using TGE;                                //TGEditクラス使用の為(解説:これがTurtleGraphics機能の肝、になります。)

namespace TGEditor
{
    public class tgEditor : Form
    {
        //クラスメンバーフィールド
        Assembly myOwn = Assembly.GetEntryAssembly();
        TGEdit tge;        //TGEditクラスインスタンス(解説:まだメモリーに生成していないので、「ポインター」の状態です。)
        //クラスメンバーコントロール
        MenuStrip menuStrip;                        //メニュー
        ToolStrip toolStrip;                        //ツールバー
        ToolStripButton[] tsButton;                    //ツールバーボタン
        StatusStrip statusStrip;                    //ステータスバー
        ToolStripStatusLabel[] tssl;                //ステータスバーラベル

        [STAThread]
        public static void Main()                    //エントリーポイント
        {
            Application.Run(new tgEditor());
        }

        public tgEditor()                            //コンストラクター
        {
            this.Icon = Icon.ExtractAssociatedIcon(myOwn.Location);    //プログラムアイコン
            this.Size = new Size(960, 640);
            this.MinimumSize = new Size(480, 320);
            this.Text = "TGEditor";
            //Drag and Dropでの処理
            this.AllowDrop = true;
            this.DragEnter += tgEditor_DragEnter;
            this.DragDrop += tgEditor_DragDrop;
            //起動時処理
            this.Load += tgEditor_Load;
            //TGEditクラスインスタンス作成と描画初期化
            tge = new TGEdit(this);
            tge.Reset();
            //*.tgeファイル用ディレクトリーの作成(初回のみ)
            Directory.CreateDirectory(".\\tgeFiles");    //解説:既にフォールダーがある場合でも例外処理にはなりません。
        }

        private void tgEditor_Load(object sender, EventArgs e)
        {
            //フォームのレイアウトを一時停止
            this.SuspendLayout();
            //ツールバーとステータスバーの設定
            MakeBars();
            //メニューの作成(MenuStripはコントロールであり、上からの並びはDock投入のFILO順となる)
            MakeMenu();
            //フォームのレイアウトを再開
            this.ResumeLayout(false);
            this.PerformLayout();
            //命令セットライブラリー(CmdList.tge)を読み込む(解説:命令セットライブラリーは一応システム管理)
            tge.CmdList.FileName = ".\\tgeFiles\\CmdList.tge";
            tge.CmdList.ReadFile();
            //起動時の引数をチェックし、引数にファイル名があればそれを読み込む(解説:これはExeListとなります。)
            string[] arg = System.Environment.GetCommandLineArgs();
            if(arg.Length > 1)
            {
                if(Path.GetExtension(arg[arg.Length - 1]) == ".tge")
                {
                    //(複数投入であれば最後の)ファイル名を記録
                    tssl[1].Text = arg[arg.Length - 1];
                    tssl[1].ToolTipText = arg[arg.Length - 1];    //ToolTip設定
                    //ExeListを初期化、ファイル読み込み
                    tge.ExeList.Clear();
                    tge.ExeList.FileName = tssl[1].Text;
                    tge.ExeList.ReadFile();
                }
                else
                {
                    //エラー処理
                    MessageBox.Show("タートルグラフィックデータファイル(*.tge)ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        //メニューの作成
        private void MakeMenu()
        {
            //メインメニュー作成
            menuStrip = new MenuStrip();
            menuStrip.SuspendLayout();
            //メインメニューアイテム付加
            ToolStripMenuItem miFile = new ToolStripMenuItem();        //「ファイル」メニュー
            miFile.Text = "ファイル(&F)";
            menuStrip.Items.Add(miFile);
            ToolStripMenuItem miEdit = new ToolStripMenuItem();        //「編集」メニュー
            miEdit.Text = "編集(&E)";
            menuStrip.Items.Add(miEdit);
            ToolStripMenuItem miExeTG = new ToolStripMenuItem();    //「実行」メニュー
            miExeTG.Text = "実行(&E)";
            menuStrip.Items.Add(miExeTG);
            ToolStripMenuItem miHelp = new ToolStripMenuItem();        //「ヘルプ」メニュー
            miHelp.Text = "ヘルプ(&H)";
            menuStrip.Items.Add(miHelp);
            //「ファイル」メニューアイテム付加
            ToolStripMenuItem miNew = new ToolStripMenuItem();        //「新規」メニューアイテム
            miNew.Text = "実行ファイルの新規作成(&N)";
            miNew.Click += OnNew_Click;
            miNew.ShortcutKeys = Keys.Control | Keys.N;
            miFile.DropDownItems.Add(miNew);
            ToolStripMenuItem miOpen = new ToolStripMenuItem();        //「開く」メニューアイテム
            miOpen.Text = "実行ファイルを開く(&O)";
            miOpen.Click += OnOpen_Click;
            miOpen.ShortcutKeys = Keys.Control | Keys.O;
            miFile.DropDownItems.Add(miOpen);
            ToolStripMenuItem miSave = new ToolStripMenuItem();        //「保存」メニューアイテム
            miSave.Text = "実行ファイルを保存(&S)";
            miSave.Click += OnSave_Click;
            miSave.ShortcutKeys = Keys.Control | Keys.S;
            miFile.DropDownItems.Add(miSave);
            ToolStripMenuItem miSaveAs = new ToolStripMenuItem();    //「名前を付けて保存」メニューアイテム
            miSaveAs.Text = "実行ファイルを名前を付けて保存(&A)";
            miSaveAs.Click += OnSaveAs_Click;
            miSaveAs.ShortcutKeys = Keys.Control | Keys.A;
            miFile.DropDownItems.Add(miSaveAs);
            miFile.DropDownItems.Add(new ToolStripSeparator());        //セパレーター
            ToolStripMenuItem miExit = new ToolStripMenuItem();        //「終了」メニューアイテム
            miExit.Text = "終了(&X)";
            miExit.Click += OnExit_Click;
            miExit.ShortcutKeys = Keys.Control | Keys.X;
            miFile.DropDownItems.Add(miExit);
            //「編集」メニューアイテム付加
            miEdit.DropDownItems.Add(new ToolStripSeparator());        //セパレーター
            ToolStripMenuItem miSetEdit = new ToolStripMenuItem();    //「命令セット作成」メニューアイテム
            miSetEdit.Text = "命令セット作成(&T)";
            miSetEdit.Click += OnSetEdit_Click;
            miSetEdit.ShortcutKeys = Keys.Control | Keys.T;
            miEdit.DropDownItems.Add(miSetEdit);
            ToolStripMenuItem miListEdit = new ToolStripMenuItem();    //「命令リスト編集」メニューアイテム
            miListEdit.Text = "命令リスト編集(&L)";
            miListEdit.Click += OnListEdit_Click;
            miListEdit.ShortcutKeys = Keys.Control | Keys.L;
            miEdit.DropDownItems.Add(miListEdit);
            miEdit.DropDownItems.Add(new ToolStripSeparator());        //セパレーター
            ToolStripMenuItem miExeList = new ToolStripMenuItem();    //「実行リスト編集」メニューアイテム
            miExeList.Text = "実行リスト編集(&E)";
            miExeList.Click += OnExeListEdit_Click;
            miExeList.ShortcutKeys = Keys.Control | Keys.E;
            miEdit.DropDownItems.Add(miExeList);
            //「実行」メニューアイテム付加
            ToolStripMenuItem miSetExe = new ToolStripMenuItem();    //「命令セット実行」メニューアイテム
            miSetExe.Text = "命令セット実行(&T)";
            miSetExe.Click += OnSetExe_Click;
            miExeTG.DropDownItems.Add(miSetExe);
            miExeTG.DropDownItems.Add(new ToolStripSeparator());        //セパレーター
            ToolStripMenuItem miExe_List = new ToolStripMenuItem();    //「実行リスト実行」メニューアイテム
            miExe_List.Text = "実行リスト実行(&E)";
            miExe_List.Click += OnExe_List_Click;
            miExeTG.DropDownItems.Add(miExe_List);
            //「ヘルプ」メニューアイテム付加
            ToolStripMenuItem miHowtoUse = new ToolStripMenuItem();    //「使い方」メニューアイテム
            miHowtoUse.Text = "使い方(&H)";
            miHowtoUse.Click += OnHowtoUse_Click;
            miHowtoUse.ShortcutKeys = Keys.Control | Keys.H;
            miHelp.DropDownItems.Add(miHowtoUse);
            ToolStripMenuItem miShortcutKey = new ToolStripMenuItem();    //「ショートカットキー」メニューアイテム
            miShortcutKey.Text = "ショートカットキー(&S)";
            miShortcutKey.Click += OnShortcutKey_Click;
            miShortcutKey.ShortcutKeys = Keys.F1;
            miHelp.DropDownItems.Add(miShortcutKey);
            ToolStripMenuItem miVer = new ToolStripMenuItem();        //「バージョン」メニューアイテム
            miVer.Text = "バージョン(&V)";
            miVer.Click += OnVersion_Click;
            miVer.ShortcutKeys = Keys.F2;
            miHelp.DropDownItems.Add(miVer);
            //メインメニューに設定して表示
            this.MainMenuStrip = menuStrip;
            this.Controls.Add(menuStrip);
            menuStrip.ResumeLayout(false);
            menuStrip.PerformLayout();
        }

        //ツールバーとステータスバーの作成
        private void MakeBars()
        {
            //ToolStripクラスインスタンスの生成
            this.toolStrip = new ToolStrip();
            //ツールバーのレイアウトを一時停止
            this.toolStrip.SuspendLayout();
            //ToolStripButton配列を作成
            this.tsButton = new ToolStripButton[11];
            //解説:以下がリソース(ツールバービットマップ)の準備処理です。

            //本プログラムの埋め込みリソースのリソースマネージャーを作成
            ResourceManager rm = new ResourceManager("TGEditor", myOwn);
            //ツールバービットマップの読み込み
            ImageList imgList = new ImageList();
            imgList.ImageSize = new Size(16, 15);
            imgList.Images.AddStrip((Bitmap)rm.GetObject("tgToolBar"));
            imgList.TransparentColor = Color.FromArgb(0xFF, 0xFF, 0xFF);    //tgToolBar.bmpの背景色

            //ToolStripButton[0]を作成
            this.tsButton[0] = new ToolStripButton();
            this.tsButton[0].Text = "実行ファイル新規作成";                    //テキスト設定
            this.tsButton[0].Image = (Bitmap)imgList.Images[0];                //画像設定
            this.tsButton[0].DisplayStyle = ToolStripItemDisplayStyle.Image;    //画像表示のみ
            this.tsButton[0].Click += OnNew_Click;                            //Clickイベントハンドラ追加(解説:メニュー連動、以下同じ。)
            this.toolStrip.Items.Add(this.tsButton[0]);                        //ボタンを追加
            //ToolStripButton[1]を作成
            this.tsButton[1] = new ToolStripButton();
            this.tsButton[1].Text = "実行ファイルを開く";                    //テキスト設定
            this.tsButton[1].Image = (Bitmap)imgList.Images[1];                //画像設定
            this.tsButton[1].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
            this.tsButton[1].Click += OnOpen_Click;                            //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[1]);                        //ボタンを追加
            //ToolStripButton[2]を作成
            this.tsButton[2] = new ToolStripButton();
            this.tsButton[2].Text = "実行ファイルの保存";                    //テキスト設定
            this.tsButton[2].Image = (Bitmap)imgList.Images[2];                //画像設定
            this.tsButton[2].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
            this.tsButton[2].Click += OnSave_Click;                            //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[2]);                        //ボタンを追加
            //セパレーターを挿入
            this.toolStrip.Items.Add(new ToolStripSeparator());
            //ToolStripButton[3]を作成
            this.tsButton[3] = new ToolStripButton();
            this.tsButton[3].Text = "終了";                                    //テキスト設定
            this.tsButton[3].Image = (Bitmap)imgList.Images[3];                //画像設定
            this.tsButton[3].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
            this.tsButton[3].Click += OnExit_Click;                            //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[3]);                        //ボタンを追加
            //セパレーターを挿入
            this.toolStrip.Items.Add(new ToolStripSeparator());
            //ToolStripButton[4]を作成
            this.tsButton[4] = new ToolStripButton();
            this.tsButton[4].Text = "命令セット作成";                        //テキスト設定
            this.tsButton[4].Image = (Bitmap)imgList.Images[4];                //画像設定
            this.tsButton[4].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
            this.tsButton[4].Click += OnSetEdit_Click;                        //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[4]);                        //ボタンを追加
            //ToolStripButton[5]を作成
            this.tsButton[5] = new ToolStripButton();
            this.tsButton[5].Text = "命令リスト編集";                        //テキスト設定
            this.tsButton[5].Image = (Bitmap)imgList.Images[5];                //画像設定
            this.tsButton[5].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
            this.tsButton[5].Click += OnListEdit_Click;                        //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[5]);                        //ボタンを追加
            //ToolStripButton[6]を作成
            this.tsButton[6] = new ToolStripButton();
            this.tsButton[6].Text = "実行リスト編集";                        //テキスト設定
            this.tsButton[6].Image = (Bitmap)imgList.Images[6];                //画像設定
            this.tsButton[6].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
            this.tsButton[6].Click += OnExeListEdit_Click;                    //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[6]);                        //ボタンを追加
            //セパレーターを挿入
            this.toolStrip.Items.Add(new ToolStripSeparator());
            //ToolStripButton[7]を作成
            this.tsButton[7] = new ToolStripButton();
            this.tsButton[7].Text = "命令セット実行";                        //テキスト設定
            this.tsButton[7].Image = (Bitmap)imgList.Images[7];                //画像設定
            this.tsButton[7].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
            this.tsButton[7].Click += OnSetExe_Click;                        //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[7]);                        //ボタンを追加
            //ToolStripButton[8]を作成
            this.tsButton[8] = new ToolStripButton();
            this.tsButton[8].Text = "実行リスト実行";                        //テキスト設定
            this.tsButton[8].Image = (Bitmap)imgList.Images[8];                //画像設定
            this.tsButton[8].DisplayStyle = ToolStripItemDisplayStyle.Image;//画像表示のみ
            this.tsButton[8].Click += OnExe_List_Click;                    //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[8]);                        //ボタンを追加
            //セパレーターを挿入
            this.toolStrip.Items.Add(new ToolStripSeparator());
            //ToolStripButton[9]を作成
            this.tsButton[9] = new ToolStripButton();
            this.tsButton[9].Text = "使い方";                                //テキスト設定
            this.tsButton[9].Image = (Bitmap)imgList.Images[9];            //画像設定
            this.tsButton[9].DisplayStyle = ToolStripItemDisplayStyle.Image;    //画像表示のみ
            this.tsButton[9].Click += OnHowtoUse_Click;                        //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[9]);                    //ボタンを追加
            //ToolStripButton[10]を作成
            this.tsButton[10] = new ToolStripButton();
            this.tsButton[10].Text = "バージョン情報(&V)";                    //テキスト設定
            this.tsButton[10].Image = (Bitmap)imgList.Images[10];            //画像設定
            this.tsButton[10].DisplayStyle = ToolStripItemDisplayStyle.Image;    //画像表示のみ
            this.tsButton[10].Click += OnVersion_Click;                        //Clickイベントハンドラ追加
            this.toolStrip.Items.Add(this.tsButton[10]);                    //ボタンを追加
            //ツールバーの設定
            this.Controls.Add(this.toolStrip);
            //ツールバーのレイアウトを再開
            this.toolStrip.ResumeLayout(false);
            this.toolStrip.PerformLayout();

            //StatusStripクラスインスタンスの生成
            this.statusStrip = new StatusStrip();
            //ステータスバーにパネルとテキストを追加
            tssl = new ToolStripStatusLabel[2];
            tssl[0] = new ToolStripStatusLabel();
            tssl[0].BorderSides = ToolStripStatusLabelBorderSides.All;
            tssl[0].BorderStyle = Border3DStyle.SunkenInner;
            tssl[0].BackColor = SystemColors.Control;
            tssl[0].Text = "TGEditor Ver. 1.0";
            tssl[0].AutoSize = true;
            tssl[0].TextAlign = ContentAlignment.MiddleLeft;
            tssl[1] = new ToolStripStatusLabel();
            tssl[1].BorderSides = ToolStripStatusLabelBorderSides.All;
            tssl[1].BorderStyle = Border3DStyle.SunkenInner;
            tssl[1].BackColor = SystemColors.Control;
            tssl[1].TextAlign = ContentAlignment.MiddleLeft;
            tssl[1].Text = "(ファイル名)";
            tssl[1].ToolTipText = "(ファイル名)";                            //ToolTip設定
            tssl[1].Spring = true;
            statusStrip.Items.AddRange(tssl);
            statusStrip.ShowItemToolTips = true;                            //ToolTip表示
            this.Controls.Add(this.statusStrip);                            //StatusStrip(ステータスバー)を追加
        }

        //ドラッグされた時
        private void tgEditor_DragEnter(object sender, DragEventArgs e)
        {
            if(e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
        }

        //ドロップされたとき
        private void tgEditor_DragDrop(object sender, DragEventArgs e)
        {
            //ドロップされたファイルパスを取得
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            if(files.Length > 0)
            {
                if(Path.GetExtension(files[files.Length - 1]) == ".tge")
                {
                    //ファイル名を記録
                    tssl[1].Text = files[files.Length - 1];
                    tssl[1].ToolTipText = files[files.Length - 1];    //ToolTip設定
                    //ExeListを初期化、ファイル読み込み
                    tge.ExeList.Clear();
                    tge.ExeList.FileName = tssl[1].Text;
                    tge.ExeList.ReadFile();
                }
                else    //エラー処理
                    MessageBox.Show("タートルグラフィックデータファイル(*.tge)ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 

前回まででTGEditorの機能のコア部分であるTGEライブラリーのコード解説を終了しましたので、いよいよ"wrap up"の段階に来ました。

 

出来上がったTGEライブラリーのソースコード(TGE.cs-注1)は「ダイナミックリンクライブラリー(DLL)」としてコンパイルします。(注2

注1【TurtleGraphics】ご参考-TGEのクラス定義部分【TurtleGraphics】ご参考-TGEのUI部分(1)【TurtleGraphics】ご参考-TGEのUI部分(2)【TurtleGraphics】ご参考-TGEのUI部分(3)を参照願います。

注2Nakov.TurtleGraphics.dllが必要です。ご参考までにBCCForm and BCCSkeltonのパッケージに入っている分のバッチファイルを紹介します。

@ECHO OFF
ECHO ----------------------------------
ECHO  TGEditor.bat
ECHO  Copyright (c) 2026 by Ysama
ECHO ----------------------------------
REM TGE.dllの作成
(解説:↓は「TGE.dllがなかったら、ターゲットをDLLとしてコンパイルする」、という意味です。)
if not exist "TGE.dll" "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe" /t:library  /reference:".\Nakov.TurtleGraphics.dll" /warn:4 ".\TGE.cs"
REM TGEditorの作成
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe" /t:winexe /win32icon:".\Turtle.ico" /res:".\TGEditor.resources" /reference:".\TGE.dll" /warn:4 ".\TGEditor.cs"
pause

 

TGE.dllができたならば、TGEditor.csに移ります。

 

先ずはツールバービットマップを用意して

 

これをC#のリソースファイル(TGEditor.resources)にします。これは専用のツールがないとできない()ので、BCCForm and BCCSkeltonのパッケージにはTGEditor.resourceというファイルを入れてあります。

:私は昔自作したResourceWriterを使っています。

 

プログラムアイコン(ウィンドウアイコンでもある)【TurtleGraphics】宿題の答えとC#5版コンパイルの準備の時の亀さんを使います。(まぁ、無くてもコンパイルはできますが...)

 

と、いうことで、

 

いよいよTGEditor.csに話を移しますが、前にも書いた通り、このプログラムコードはここで取り上げたRichEditorからの流用ですのであまり目新しいものはありません。又量も622行だけなので、次回に(最後の)コード解説にするつもりです。

 

長々とC#のコードを並べた

 

ので一息つくために久々の食べ物の話を。

 

昨日のお昼は、最近凝っていて前に作って余りを冷凍していた

 

キノコ炊き込みご飯

 

を、これも(お酒のお供に)冷凍で取り寄せていた「ホッケの昆布醤油漬け」と(揚皮と中の豆腐の食感差が好みの)生揚げを

 

久々にご飯のおかず(笑)

 

にしてしっかりと焼き、野沢菜と一緒においしくいただきました。又、炊き込みご飯が少ないのと野菜が足りないので、

 

野菜たっぷりの中華風春雨スープ

 

も戴きました。

 

 

ps. 炊き込みご飯は具材(特にキノコ)の食感が落ちるので冷凍には向いていないことを肝に銘じました。なお、醤油の代わりに生揚げにご飯に掛けるワカメやジャコのふりかけをかけて食べるのがマイブームです。

 

で、何が面白いのかって?

 

矢張り色々と工夫して作ったり、組み合わせて「試してみる」ってことかな?

 

///////////////////////////////////////////////////////////////////////////////
//                      TGEライブラリー (TGE.dll)
//                     Copyright (c) 2026 by Ysama
//
//                               【概要】
//LOGOベースの描画命令を纏めた「命令セット(TGSet)」、その一覧である「命令リス
//ト(TGList)」、「命令リスト」から指定した命令セットで、繰り返しを含め実行順を
//定める「実行リスト(TGList)」及び編集ダイアログをまとめたNakov.TurtleGraphics
//の命令編集ライブラリー
///////////////////////////////////////////////////////////////////////////////

続きの続きの続き

 

    /////////////////////////
    // Command入力ダイアログ
    /////////////////////////

    class InputDlg : Form
    {
        //クラスフィールド
        string[] CmdNameList = new string[15] {"Nop", "Forward()", "Backward()",
                                                "MoveTo()", "Rotate()", "RotateTo()",
                                                "PenUp()", "PenDown()", "X",
                                                "Y", "Angle", "PenColor",
                                                "PenSize", "PenVisible", "Delay"};
        string[] CmdExplList = new string[15] {"何もしない", "前進する", "後退する",
                                                "絶対座標へ移動する", "現在の方向から指定角度回転", "絶対角度へ回転(↑0→90↓180←270)",
                                                "描画停止", "描画開始", "X座標指定(移動)",
                                                "X座標指定(移動)", "角度指定(↑0→90↓180←270)",
                                                "描画色指定(Color)", "描画幅指定", "可視可(1)、不可(0)", "中断時間(ms)"};
        //クラスプロパティ
        public int[] dtData {get; set;}
        public string[] dtCmd;
        //クラスコントロール
        Button BtnOK;
        Button BtnCancel;
        GroupBox gBox;
        ComboBox cbCommands;
        TextBox txbExplanation;
        Label[] labelCmd;
        TextBox[] txbStr;

        //コンストラクター(1)-解説:引数無し(新規入力)
        public InputDlg()
        {
            dtData = new int[] {-1, 0, 0, 0};        //ComboBoxが選択されていない状態のSelectedIndex値
            dtCmd = new string[] {"", ""};            //命令文と説明文
            InitializeControls();
        }

        //コンストラクター(2)-解説:引数あり(編集)
        public InputDlg(int[] arg_Data)
        {
            //引数の記録
            if(arg_Data[0] >= 0 && arg_Data[0] < CmdNameList.Length)
                dtData = (int[])arg_Data.Clone();    //arg_Data配列のクローンで初期化
            else
                dtData = new int[] {-1, 0, 0, 0};    //ComboBoxが選択されていない状態のSelectedIndex値
            dtCmd = new string[] {"", ""};            //命令文と説明文
            InitializeControls();
        }

        //コントロールの初期化
        private void InitializeControls()
        {
            //ダイアログの属性設定
            if(dtData[0] == -1)
                this.Text = "命令入力ダイアログ";
            else
                this.Text = "命令編集ダイアログ";
            this.ClientSize = new Size(320, 210);
            this.MaximizeBox = false;        //最大化ボタン
            this.MinimizeBox = false;        //最小化ボタン
            this.ShowInTaskbar = false;        //タスクバー上非表示
            this.FormBorderStyle = FormBorderStyle.FixedDialog;        //境界のスタイル
            this.StartPosition = FormStartPosition.CenterScreen;    //画面中央に配置

            //コントロールの属性設定
            BtnOK = new Button();
            BtnOK.Location = new Point(ClientSize.Width - BtnOK.Width - 20, ClientSize.Height - BtnOK.Height - 10);
            BtnOK.Text = "OK";
            BtnOK.AutoSize = true;
            BtnOK.Click += new EventHandler(OnOK_Click);

            BtnCancel = new Button();
            BtnCancel.Location = new Point(20, ClientSize.Height - BtnCancel.Height - 10);
            BtnCancel.Text = "Cancel";
            BtnCancel.AutoSize = true;
            BtnCancel.Click += new EventHandler(OnCancel_Click);

            gBox = new GroupBox();
            gBox.Location = new Point(10, 0);
            gBox.Size = new Size(ClientSize.Width - 20, ClientSize.Height - BtnOK.Height - 20);
            gBox.Text = "命令と引数1~3の設定";

            cbCommands =new ComboBox();
            cbCommands.Location = new Point(10, 16);
            cbCommands.Size = new Size(ClientSize.Width / 2, 28);
            cbCommands.DropDownWidth = ClientSize.Width / 2;
            cbCommands.DropDownHeight = 160;
            cbCommands.DropDownStyle = ComboBoxStyle.DropDownList;
            cbCommands.FormattingEnabled = true;
            cbCommands.TextChanged += Command_TextChanged;

            txbExplanation = new TextBox();
            txbExplanation.Location = new Point(10, 40);
            txbExplanation.Size = new Size(ClientSize.Width / 2, 120);
            txbExplanation.Multiline = true;
            txbExplanation.WordWrap = true;
            txbExplanation.BorderStyle = BorderStyle.Fixed3D;
            txbExplanation.ReadOnly = true;

            labelCmd = new Label[3];
            labelCmd[0] = new Label();
            labelCmd[0].Text = "引数1(定数)";
            labelCmd[0].Size = new Size(80, 18);
            labelCmd[0].Location = new Point(180, 20);
            labelCmd[1] = new Label();
            labelCmd[1].Text = "引数2(倍数)";
            labelCmd[1].Location = new Point(180, 70);
            labelCmd[1].Size = new Size(80, 18);
            labelCmd[2] = new Label();
            labelCmd[2].Text = "引数3(分子)";
            labelCmd[2].Location = new Point(180, 120);
            labelCmd[2].Size = new Size(80, 18);

            txbStr = new TextBox[3];
            txbStr[0] = new TextBox();
            txbStr[0].Location = new Point(180, 38);
            txbStr[0].Size = new Size(100, 28);
            txbStr[0].BorderStyle = BorderStyle.Fixed3D;
            txbStr[0].Text = "0";
            txbStr[0].TextAlign = HorizontalAlignment.Right;
            txbStr[0].Enter += txbStr0_Enter;
            txbStr[1] = new TextBox();
            txbStr[1].Size = new Size(100, 28);
            txbStr[1].Location = new Point(180, 88);
            txbStr[1].BorderStyle = BorderStyle.Fixed3D;
            txbStr[1].Text = "0";
            txbStr[1].TextAlign = HorizontalAlignment.Right;
            txbStr[1].Enter += txbStr1_Enter;
            txbStr[2] = new TextBox();
            txbStr[2].Size = new Size(100, 28);
            txbStr[2].Location = new Point(180, 138);
            txbStr[2].BorderStyle = BorderStyle.Fixed3D;
            txbStr[2].Text = "0";
            txbStr[2].TextAlign = HorizontalAlignment.Right;
            txbStr[2].Enter += txbStr2_Enter;

            gBox.Controls.Add(cbCommands);
            gBox.Controls.Add(txbExplanation);
            gBox.Controls.Add(labelCmd[0]);
            gBox.Controls.Add(labelCmd[1]);
            gBox.Controls.Add(labelCmd[2]);
            gBox.Controls.Add(txbStr[0]);
            gBox.Controls.Add(txbStr[1]);
            gBox.Controls.Add(txbStr[2]);
            this.Controls.Add(BtnOK);
            this.Controls.Add(BtnCancel);
            this.Controls.Add(gBox);

            //cbCommands、txbStrの初期設定
            cbCommands.Items.AddRange(CmdNameList);
            if(dtData[0] >= 0 && dtData[0] < CmdNameList.Length)
            {
                cbCommands.SelectedIndex = dtData[0];
            }
            if(dtData[1] != 0)
            {
                txbStr[0].Text = dtData[1].ToString();
            }
            if(dtData[2] != 0)
            {
                txbStr[1].Text = dtData[2].ToString();
            }
            if(dtData[3] != 0)
            {
                txbStr[2].Text = dtData[3].ToString();
            }
        }

        private void Command_TextChanged(object sender, EventArgs e)
        {
            dtData[0] = cbCommands.SelectedIndex;
            txbExplanation.Text = CmdExplList[dtData[0]];
            if(dtData[0] == 11)    //解説:元々はPenColor以外はtrueにするelse節がありました。
            {
                txbStr[1].Enabled = false;
                txbStr[2].Enabled = false;
            }
        }

        private void txbStr0_Enter(object sender, EventArgs e)
        {
            string msg = "命令に与えられる「引数1(定数) + 引数2 * 繰り返し数(倍数) + 引数3 / (最大繰り返し数 - 繰り返し数)(分子)」の定数部分です。";
            if(dtData[0] == 3)
                msg = "MoveTo(x, y)の場合引数1がx、引数2がyで、引数3の繰り返し回数の倍数が加算されます。(x = 引数1 + 引数3 x 繰り返し数、y = 引数2 + 引数3 x 繰り返し数)";
            else if(dtData[0] == 11)
            {
                msg = "PenColor()の場合、引数1にColor.FromArgb(RGB値)のRGB値が入ります。";
                ColorDialog colDlg = new ColorDialog();
                colDlg.AllowFullOpen = true;
                if(colDlg.ShowDialog() == DialogResult.OK)
                {
                    txbStr[0].Text = colDlg.Color.ToArgb().ToString();
                    colDlg.Dispose();
                }    //解説:繰り返し回数による変数変化を与えるために、TextBoxを有効化し、入力可としました。
                txbStr[1].Enabled = true;
                txbStr[2].Enabled = true;
            }
            txbExplanation.Text = msg;
        }

        private void txbStr1_Enter(object sender, EventArgs e)
        {
            string msg = "命令に与えられる「引数1(定数) + 引数2 * 繰り返し数(倍数) + 引数3 / (最大繰り返し数 - 繰り返し数)(分子)」の倍数部分です。";
            if(dtData[0] == 3)
                msg = "MoveTo(x, y)の場合引数1がx、引数2がyで、引数3の繰り返し回数の倍数が加算されます。(x = 引数1 + 引数3 x 繰り返し数、y = 引数2 + 引数3 x 繰り返し数)";
            txbExplanation.Text = msg;
        }

        private void txbStr2_Enter(object sender, EventArgs e)
        {
            string msg = "命令に与えられる「引数1(定数) + 引数2 * 繰り返し数(倍数) + 引数3 / (最大繰り返し数 - 繰り返し数)(分子)」の分子部分です。";
            if(dtData[0] == 3)
                msg = "MoveTo(x, y)の場合引数1がx、引数2がyで、引数3の繰り返し回数の倍数が加算されます。(x = 引数1 + 引数3 x 繰り返し数、y = 引数2 + 引数3 x 繰り返し数)";
            txbExplanation.Text = msg;
        }

        //OKボタンがクリックされた時
        protected void OnOK_Click(object sender, EventArgs e)
        {
            if(dtData[0] < 0)
                MessageBox.Show("命令が選択されていません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
            else
            {
                dtCmd[0] = CmdNameList[dtData[0]];        //命令文
                dtCmd[1] = CmdExplList[dtData[0]];        //説明文
                int dat = 0;
                if(!int.TryParse(txbStr[0].Text, out dat))
                    MessageBox.Show("引数1が整数ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                else
                {
                    dtData[1] = dat;
                    if(!int.TryParse(txbStr[1].Text, out dat))
                        MessageBox.Show("引数2が整数ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    else
                    {
                        dtData[2] = dat;
                        if(!int.TryParse(txbStr[2].Text, out dat))
                            MessageBox.Show("引数3が整数ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        else
                        {
                            dtData[3] = dat;
                            Close();
                        }
                    }
                }
            }
        }

        //Cancelボタンがクリックされた時
        protected void OnCancel_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}

 

///////////////////////////////////////////////////////////////////////////////
//                      TGEライブラリー (TGE.dll)
//                     Copyright (c) 2026 by Ysama
//
//                               【概要】
//LOGOベースの描画命令を纏めた「命令セット(TGSet)」、その一覧である「命令リス
//ト(TGList)」、「命令リスト」から指定した命令セットで、繰り返しを含め実行順を
//定める「実行リスト(TGList)」及び編集ダイアログをまとめたNakov.TurtleGraphics
//の命令編集ライブラリー
///////////////////////////////////////////////////////////////////////////////

続きの続き

 

    ///////////////////
    //CmdSetダイアログ
    ///////////////////

    public class CmdSetDlg : Form
    {
        //クラスメンバーフィールド
        public TGSet Tgs;            //TGSetクラスインスタンス
        Button Btn_Add;                //命令追加ボタン
        Button Btn_Del;                //命令削除ボタン
        Button Btn_Init;            //初期化ボタン
        Button Btn_OK;                //OKボタン
        Button Btn_Cancel;            //Cancelボタン
        ListView listView;            //リストビュー
        Label lblTimes;                //繰り返し回数ラベル
        TextBox txbTimes;            //繰り返し回数入力用
        Button Btn_Name;            //名前・説明ボタン
        Label lblName;                //命令セット名ラベル
        TextBox txbName;            //命令セット名入力用
        Label lblDescription;        //説明ラベル
        TextBox txbDescription;        //説明入力用

        //コンストラクター(1)
        public CmdSetDlg()
        {
            this.ShowIcon = false;
            this.Text = "命令セット入力ダイアログ";
            this.ClientSize = new Size(594, 320);
            this.MinimumSize = new Size(430, 340);
            this.BackColor = SystemColors.Window;
            this.Load += new EventHandler(CmdSetDlg_OnLoad);
            this.Tgs = new TGSet();                    //命令セット
            this.Tgs.AddCmd(new int[] {-1,1,0,0});    //命令セット開始
        }

        //コンストラクター(2)
        public CmdSetDlg(TGSet tgs)
        {
            this.ShowIcon = false;
            this.Text = "命令セット編集ダイアログ";
            this.ClientSize = new Size(594, 320);
            this.MinimumSize = new Size(430, 340);
            this.BackColor = SystemColors.Window;
            this.Load += new EventHandler(CmdSetDlg_OnLoad);
            this.Tgs = tgs;                            //命令セット参照渡し
        }

        //OnLoad時処理
        protected void CmdSetDlg_OnLoad(object sender, EventArgs e)
        {
            Btn_Add = new Button();
            Btn_Add.Text = "命令追加";
            Btn_Add.TextAlign = ContentAlignment.MiddleCenter;
            Btn_Add.Font = new Font("MS 明朝", 8);
            Btn_Add.ForeColor = Color.Black;
            Btn_Add.Size = new Size(80, 28);
            Btn_Add.BackColor = SystemColors.Control;
            Btn_Add.Location = new Point(ClientSize.Width - Btn_Add.Width - 10, 10);
            Btn_Add.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
            Btn_Add.Click += new EventHandler(OnClick_Add);    

            Btn_Del = new Button();
            Btn_Del.Text = "命令削除";
            Btn_Del.TextAlign = ContentAlignment.MiddleCenter;
            Btn_Del.Font = new Font("MS 明朝", 8);
            Btn_Del.ForeColor = Color.Black;
            Btn_Del.Size = new Size(80, 28);
            Btn_Del.BackColor = SystemColors.Control;
            Btn_Del.Location = new Point(ClientSize.Width - Btn_Del.Width - 10, 20 + Btn_Add.Height);
            Btn_Del.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
            Btn_Del.Click += new EventHandler(OnClick_Del);

            Btn_Init = new Button();
            Btn_Init.Text = "命令初期化";
            Btn_Init.TextAlign = ContentAlignment.MiddleCenter;
            Btn_Init.Font = new Font("MS 明朝", 8);
            Btn_Init.ForeColor = Color.Black;
            Btn_Init.Size = new Size(80, 28);
            Btn_Init.BackColor = SystemColors.Control;
            Btn_Init.Location = new Point(ClientSize.Width - Btn_Init.Width - 10, 30 + Btn_Add.Height + Btn_Del.Height);
            Btn_Init.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
            Btn_Init.Click += new EventHandler(OnClick_Init);

            Btn_OK = new Button();
            Btn_OK.Text = "OK";
            Btn_OK.TextAlign = ContentAlignment.MiddleCenter;
            Btn_OK.Font = new Font("MS 明朝", 8);
            Btn_OK.ForeColor = Color.Black;
            Btn_OK.Size = new Size(80, 28);
            Btn_OK.BackColor = SystemColors.Control;
            Btn_OK.Location = new Point(ClientSize.Width - Btn_OK.Width - 10, ClientSize.Height - Btn_OK.Height - 10);
            Btn_OK.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
            Btn_OK.Click += new EventHandler(OnClick_OK);

            Btn_Cancel = new Button();
            Btn_Cancel.Text = "Cancel";
            Btn_Cancel.TextAlign = ContentAlignment.MiddleCenter;
            Btn_Cancel.Font = new Font("MS 明朝", 8);
            Btn_Cancel.ForeColor = Color.Black;
            Btn_Cancel.Size = new Size(80, 28);
            Btn_Cancel.BackColor = SystemColors.Control;
            Btn_Cancel.Location = new Point(ClientSize.Width - Btn_Cancel.Width - 10, ClientSize.Height - Btn_Cancel.Height - Btn_OK.Height - 20);
            Btn_Cancel.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
            Btn_Cancel.Click += new EventHandler(OnClick_Cancel);

            lblTimes = new Label();
            lblTimes.Size = new Size(80, 28);
            lblTimes.Location = new Point(ClientSize.Width - lblTimes.Width - 10, 40 + Btn_Add.Height + Btn_Del.Height + Btn_Init.Height);
            lblTimes.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
            lblTimes.AutoSize = false;
            lblTimes.TextAlign = ContentAlignment.MiddleCenter;
            lblTimes.Font = new Font("MS 明朝", 8);
            lblTimes.Text = "繰り返し回数";

            txbTimes = new TextBox();
            txbTimes.Size = new Size(80, 28);
            txbTimes.Location = new Point(ClientSize.Width - lblTimes.Width - 10, 40 + Btn_Add.Height + Btn_Del.Height + Btn_Init.Height + lblTimes.Height);
            txbTimes.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
            txbTimes.TextAlign = HorizontalAlignment.Right;
            txbTimes.Text ="1";

            Btn_Name = new Button();
            Btn_Name.Text = "名前・説明";
            Btn_Name.TextAlign = ContentAlignment.MiddleCenter;
            Btn_Name.Font = new Font("MS 明朝", 8);
            Btn_Name.ForeColor = Color.Black;
            Btn_Name.Size = new Size(80, 28);
            Btn_Name.BackColor = SystemColors.Control;
            Btn_Name.Location = new Point(ClientSize.Width - Btn_Init.Width - 10, 50 + Btn_Add.Height + Btn_Del.Height + Btn_Init.Height + lblTimes.Height + txbTimes.Height);
            Btn_Name.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
            Btn_Name.Click += new EventHandler(OnClick_Name);

            lblName = new Label();
            lblName.Size = new Size(80, 18);
            lblName.Location = new Point(10, 10);
            lblName.Anchor = (AnchorStyles.Top | AnchorStyles.Left);
            lblName.AutoSize = false;
            lblName.Font = new Font("MS 明朝", 8);
            lblName.Text = "命令セット名";
            lblName.Visible = false;

            txbName = new TextBox();
            txbName.Size = new Size(ClientSize.Width - Btn_Add.Width - 30, 28);
            txbName.Location = new Point(10, lblName.Height + 10);
            txbName.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right);
            txbName.Visible = false;

            lblDescription = new Label();
            lblDescription.Size = new Size(80, 18);
            lblDescription.Location = new Point(10, lblName.Height + txbName.Height + 20);
            lblDescription.Anchor = (AnchorStyles.Top | AnchorStyles.Left);
            lblDescription.AutoSize = false;
            lblDescription.Font = new Font("MS 明朝", 8);
            lblDescription.Text = "説明";
            lblDescription.Visible = false;

            txbDescription = new TextBox();
            txbDescription.Size = new Size(ClientSize.Width - Btn_Add.Width - 30, ClientSize.Height - lblName.Height - txbName.Height - lblDescription.Height - 30);
            txbDescription.Location = new Point(10, lblName.Height + txbName.Height + lblDescription.Height + 20);
            txbDescription.Multiline = true;
            txbDescription.WordWrap = true;
            txbDescription.ScrollBars = ScrollBars.Vertical;
            txbDescription.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);
            txbDescription.Visible = false;

            this.Controls.Add(Btn_Add);
            this.Controls.Add(Btn_Del);
            this.Controls.Add(Btn_Init);
            this.Controls.Add(lblTimes);
            this.Controls.Add(txbTimes);
            this.Controls.Add(Btn_Name);
            this.Controls.Add(Btn_Cancel);
            this.Controls.Add(Btn_OK);
            this.Controls.Add(lblName);
            this.Controls.Add(txbName);
            this.Controls.Add(lblDescription);
            this.Controls.Add(txbDescription);

            //リストビュー
            listView = new ListView();
            listView.BorderStyle = BorderStyle.Fixed3D;                //境界
            listView.Location = new Point(10, 10);                    //位置
            listView.Width = ClientSize.Width - Btn_Add.Width - 30;    //サイズ
            listView.Height = ClientSize.Height - 20;
            listView.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);    //アンカー固定
            listView.FullRowSelect = true;                            //一行選択
            listView.MultiSelect = false;                            //複数選択不可
            listView.GridLines = true;                                //グリッドラインの表示
            listView.HoverSelection = false;                        //ポイントで選択できるようにする
            listView.Activation = ItemActivation.OneClick;            //シングルクリック選択;
            listView.CheckBoxes = false;                            //チェックボックス無効化
            listView.View = View.Details;                            //リストビューの表示方法
            listView.AllowDrop = false;                                //listViewへのドロップを受け入れない
            //イベントハンドラー
            listView.MouseDoubleClick+= new MouseEventHandler(ListView_DoubleClick);
            //ヘッダー定義
            ColumnHeader columnCmd = new ColumnHeader{Text = "命令", Width = 80};
            ColumnHeader columnExp = new ColumnHeader{Text = "説明", Width = 220};
            ColumnHeader columnArg1 = new ColumnHeader{Text = "引数1", Width = 60};
            columnArg1.TextAlign = HorizontalAlignment.Center;
            ColumnHeader columnArg2 = new ColumnHeader{Text = "引数2", Width = 60};
            columnArg2.TextAlign = HorizontalAlignment.Center;
            ColumnHeader columnArg3 = new ColumnHeader{Text = "引数3", Width = 60};
            columnArg3.TextAlign = HorizontalAlignment.Center;
            ColumnHeader columnCmdNo = new ColumnHeader{Text = "命令番号", Width = 60};
            columnCmdNo.TextAlign = HorizontalAlignment.Center;
            ColumnHeader[] colHeaderRegValue = {columnCmd, columnExp, columnArg1, columnArg2, columnArg3, columnCmdNo};    //ヘッダー設定
            listView.Columns.AddRange(colHeaderRegValue);    //ヘッダー追加
            //編集ダイアログの場合の初期設定
            if(Tgs.Count() > 1)
            {
                string[] CmdNameList = new string[15] {"Nop", "Forward()", "Backward()",
                                                "MoveTo()", "Rotate()", "RotateTo()",
                                                "PenUp()", "PenDown()", "X",
                                                "Y", "Angle", "PenColor",
                                                "PenSize", "PenVisible", "Delay"};
                string[] CmdExplList = new string[15] {"何もしない", "前進する", "後退する",
                                                "絶対座標へ移動する", "現在の方向から指定角度回転", "絶対角度へ回転(↑0→90↓180←270)",
                                                "描画停止", "描画開始", "X座標指定(移動)",
                                                "X座標指定(移動)", "角度指定(↑0→90↓180←270)",
                                                "描画色指定(Color)", "描画幅指定", "可視可(1)、不可(0)", "中断時間(ms)"};
                for(int i = 1; i < Tgs.Count(); i++)
                {
                    int[] cmd = Tgs.GetCmd(i);
                    string[] item = {CmdNameList[cmd[0]], CmdExplList[cmd[0]],
                                    cmd[1].ToString(), cmd[2].ToString(), 
                                    cmd[3].ToString(), cmd[0].ToString()};
                    listView.Items.Add(new ListViewItem(item));
                }
                txbName.Text = Tgs.Name;                //命令セット名
                txbDescription.Text = Tgs.Description;    //説明
                int[] hedder = Tgs.GetCmd(0);            //"-1"のある最初の命令行を取得
                txbTimes.Text = hedder[1].ToString();    //"-1"の次が繰り返し回数
            }
            //FormにListViewを追加
            this.Controls.Add(listView);
        }

        //終了時処理
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            DialogResult dr = MessageBox.Show("終了しますか?", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if(dr == DialogResult.No)
            {
                e.Cancel = true;
            }
        }

        //Addボタンがクリックされた時
        protected void OnClick_Add(object sender, EventArgs e)
        {
            //入力ダイアログによる入力
            InputDlg inpDlg = new InputDlg();
            inpDlg.ShowDialog();
            if(inpDlg.dtData[0] == -1)
                MessageBox.Show("入力がキャンセルされました。", "注意", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            else
            {
                //原本のリストに追加
                Tgs.AddCmd(inpDlg.dtData);
                //その内容をListViewに表示
                string[] item = {inpDlg.dtCmd[0], inpDlg.dtCmd[1],
                                inpDlg.dtData[1].ToString(), inpDlg.dtData[2].ToString(), 
                                inpDlg.dtData[3].ToString(), inpDlg.dtData[0].ToString()};
                listView.Items.Add(new ListViewItem(item));
            }
            inpDlg.Dispose();
        }

        //Delボタンがクリックされた時
        protected void OnClick_Del(object sender, EventArgs e)
        {
            //選択された行を確認する
            if(listView.SelectedItems.Count == 0)
                MessageBox.Show("データが選択されていません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            else
            {
                int selected_index = listView.SelectedIndices[0];
                Tgs.RemoveAt(selected_index + 1);    //Tgs.CmdSetはlistViewよりも1行多い
                listView.Items.RemoveAt(selected_index);
            }
        }

        //Initボタンがクリックされた時
        protected void OnClick_Init(object sender, EventArgs e)
        {
            Tgs.Clear();
            listView.Items.Clear();
        }

        //OKボタンがクリックされた時
        protected void OnClick_OK(object sender, EventArgs e)
        {
            int times = 0;
            if(int.TryParse(txbTimes.Text, out times))
                Tgs.SetCmd(0, -1, times, 0, 0);        //TgsのCmdSet[0]に"-1,回数,0,0"を代入"
            else
            {    //繰り返し回数が異常値の場合は終了させない
                MessageBox.Show("繰り返し回数が整数ではありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            //受け渡しデータに値を入れる
            Tgs.Name = txbName.Text;
            Tgs.Description = txbDescription.Text;
            //このフォームの戻り値
            DialogResult = DialogResult.OK;
            Close();
        }

        //Cancelボタンがクリックされた時
        protected void OnClick_Cancel(object sender, EventArgs e)
        {
            //受け渡しデータを初期化する(編集モードでTGSetの参照入力をしている場合、注意が必要!)
            Tgs.Clear();
            Tgs.Name = String.Empty;
            Tgs.Description = String.Empty;
            //このフォームの戻り値
            DialogResult = DialogResult.Cancel;
            Close();
        }

        //Namelボタンがクリックされた時(解説:これが「早変わり」の舞台裏)
        protected void OnClick_Name(object sender, EventArgs e)
        {
            if(Btn_Name.Text == "名前・説明")
            {
                Btn_Name.Text = "命令セット";
                listView.Visible = false;
                Btn_Add.Visible = false;
                Btn_Del.Visible = false;
                Btn_Init.Visible = false;
                lblTimes.Visible = false;
                txbTimes.Visible = false;
                lblName.Visible = true;
                txbName.Visible = true;
                lblDescription.Visible = true;
                txbDescription.Visible = true;
            }
            else
            {
                Btn_Name.Text = "名前・説明";
                listView.Visible = true;
                Btn_Add.Visible = true;
                Btn_Del.Visible = true;
                Btn_Init.Visible = true;
                lblTimes.Visible = true;
                txbTimes.Visible = true;
                lblName.Visible = false;
                txbName.Visible = false;
                lblDescription.Visible = false;
                txbDescription.Visible = false;
            }
        }

        //listViewがダブルクリックされた時
        protected void ListView_DoubleClick(object sender, MouseEventArgs e)
        {
            //選択された項目があるか確認
            if(listView.SelectedIndices.Count > 0)
            {
                //入力ダイアログによる入力
                int selected_index = listView.SelectedIndices[0];
                InputDlg inpDlg = new InputDlg(Tgs.GetCmd(selected_index + 1));
                inpDlg.ShowDialog(this);
                //入力ダイアログによる入力
                if(inpDlg.dtData[0] == -1)
                    MessageBox.Show("入力がキャンセルされました。", "注意", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                else
                {
                    Tgs.SetCmd(selected_index + 1, (int[])inpDlg.dtData.Clone());    //Tgs.CmdSetはlistViewよりも1行多い
                    listView.Items[selected_index].SubItems[0].Text = inpDlg.dtCmd[0];
                    listView.Items[selected_index].SubItems[1].Text = inpDlg.dtCmd[1];
                    listView.Items[selected_index].SubItems[2].Text = inpDlg.dtData[1].ToString();
                    listView.Items[selected_index].SubItems[3].Text = inpDlg.dtData[2].ToString();
                    listView.Items[selected_index].SubItems[4].Text = inpDlg.dtData[3].ToString();
                    listView.Items[selected_index].SubItems[5].Text = inpDlg.dtData[0].ToString();
                }
                inpDlg.Dispose();
            }
        }
    }
 

前回のご参考で予告いたしましたダイアログ部分のコードを「ご参考」として掲載します。今回字数制限に引っかかり、なんと三分割となりました。ご容赦を。

尚、TGEditorの本体部分についてその解説が終わってからとなります。

 

///////////////////////////////////////////////////////////////////////////////
//                      TGEライブラリー (TGE.dll)
//                     Copyright (c) 2026 by Ysama
//
//                               【概要】
//LOGOベースの描画命令を纏めた「命令セット(TGSet)」、その一覧である「命令リス
//ト(TGList)」、「命令リスト」から指定した命令セットで、繰り返しを含め実行順を
//定める「実行リスト(TGList)」及び編集ダイアログをまとめたNakov.TurtleGraphics
//の命令編集ライブラリー
///////////////////////////////////////////////////////////////////////////////

続き

 

    ////////////////////
    //CmdListダイアログ
    ////////////////////

    public class CmdListDlg : Form
    {
        public int Selection {get; private set;}    //戻り値
        //クラスメンバーフィールド
        int ListType;                                //リストタイプ(0-単純選択、1-CmdList、2-ExeList)
        TGEdit Tge;                                    //TGEditクラス
        TGList Tgl;                                    //TGListクラス
        Button Btn_Add;                                //命令追加ボタン
        Button Btn_Del;                                //命令削除ボタン
        Button Btn_Init;                            //初期化ボタン
        Button Btn_OK;                                //OKボタン
        Button Btn_Cancel;                            //Cancelボタン
        ListView listView;                            //リストビュー

        //コンストラクター
        public CmdListDlg(TGEdit tge, int type = 0)    //解説:引数のtgeはデータ参照、typeは用途分けの為
        {
            ListType = (type < 0 || type > 2) ? 1 : type;    //規定値はCmdList
            Tge = tge;                                        //参照渡し
            switch(ListType)
            {    //リストタイプによるタイトルとデータソースの決定(解説:このように使い分けている)
                case 0:        //値渡しによる選択
                    this.Text = "命令セット選択";
                    Tgl = new TGList(Tge.CmdList);
                    break;
                case 1:        //参照渡しによる直接編集
                    this.Text = "命令セットライブラリー";
                    Tgl = Tge.CmdList;
                    break;
                case 2:        //参照渡しによる直接編集
                    this.Text = "実行命令セット一覧";
                    Tgl = Tge.ExeList;
                    break;
            }
            this.ShowIcon = false;
            this.ClientSize = new Size(640, 320);
            this.MinimumSize = new Size(480, 240);
            this.BackColor = SystemColors.Window;
            this.Load += new EventHandler(CmdListDlg_OnLoad);
        }

        //OnLoad時処理
        protected void CmdListDlg_OnLoad(object sender, EventArgs e)
        {
            Btn_Add = new Button();
            Btn_Add.Text = "命令セット追加";
            Btn_Add.TextAlign = ContentAlignment.MiddleCenter;
            Btn_Add.Font = new Font("MS 明朝", 8);
            Btn_Add.ForeColor = Color.Black;
            Btn_Add.Size = new Size(100, 28);
            Btn_Add.BackColor = SystemColors.Control;
            Btn_Add.Location = new Point(ClientSize.Width - Btn_Add.Width - 10, 10);
            Btn_Add.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
            Btn_Add.Click += new EventHandler(OnClick_Add);
            Btn_Add.Visible = (ListType == 0) ? false : true;    //解説:引数typeにより表示したり、しなかったり。(以下略)

            Btn_Del = new Button();
            Btn_Del.Text = "命令セット削除";
            Btn_Del.TextAlign = ContentAlignment.MiddleCenter;
            Btn_Del.Font = new Font("MS 明朝", 8);
            Btn_Del.ForeColor = Color.Black;
            Btn_Del.Size = new Size(100, 28);
            Btn_Del.BackColor = SystemColors.Control;
            Btn_Del.Location = new Point(ClientSize.Width - Btn_Del.Width - 10, 20 + Btn_Add.Height);
            Btn_Del.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
            Btn_Del.Click += new EventHandler(OnClick_Del);
            Btn_Del.Visible = (ListType == 0) ? false : true;

            Btn_Init = new Button();
            Btn_Init.Text = "命令リスト初期化";
            Btn_Init.TextAlign = ContentAlignment.MiddleCenter;
            Btn_Init.Font = new Font("MS 明朝", 8);
            Btn_Init.ForeColor = Color.Black;
            Btn_Init.Size = new Size(100, 28);
            Btn_Init.BackColor = SystemColors.Control;
            Btn_Init.Location = new Point(ClientSize.Width - Btn_Init.Width - 10, 30 + Btn_Add.Height + Btn_Del.Height);
            Btn_Init.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
            Btn_Init.Click += new EventHandler(OnClick_Init);
            Btn_Init.Visible = (ListType == 0) ? false : true;

            Btn_OK = new Button();
            Btn_OK.Text = "OK";
            Btn_OK.TextAlign = ContentAlignment.MiddleCenter;
            Btn_OK.Font = new Font("MS 明朝", 8);
            Btn_OK.ForeColor = Color.Black;
            Btn_OK.Size = new Size(100, 28);
            Btn_OK.BackColor = SystemColors.Control;
            Btn_OK.Location = new Point(ClientSize.Width - Btn_OK.Width - 10, ClientSize.Height - Btn_OK.Height - 10);
            Btn_OK.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
            Btn_OK.Click += new EventHandler(OnClick_OK);

            Btn_Cancel = new Button();
            Btn_Cancel.Text = "Cancel";
            Btn_Cancel.TextAlign = ContentAlignment.MiddleCenter;
            Btn_Cancel.Font = new Font("MS 明朝", 8);
            Btn_Cancel.ForeColor = Color.Black;
            Btn_Cancel.Size = new Size(100, 28);
            Btn_Cancel.BackColor = SystemColors.Control;
            Btn_Cancel.Location = new Point(ClientSize.Width - Btn_Cancel.Width - 10, ClientSize.Height - Btn_Cancel.Height - Btn_OK.Height - 20);
            Btn_Cancel.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
            Btn_Cancel.Click += new EventHandler(OnClick_Cancel);

            this.Controls.Add(Btn_Add);
            this.Controls.Add(Btn_Del);
            this.Controls.Add(Btn_Init);
            this.Controls.Add(Btn_Cancel);
            this.Controls.Add(Btn_OK);

            //リストビュー
            listView = new ListView();
            listView.BorderStyle = BorderStyle.Fixed3D;                    //境界
            listView.Location = new Point(10, 10);                        //位置
            listView.Width = ClientSize.Width - Btn_Add.Width - 30;        //サイズ
            listView.Height = ClientSize.Height - 20;
            listView.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);    //アンカー固定
            listView.FullRowSelect = true;                                //一行選択
            listView.MultiSelect = true;                                //複数選択を許す
            listView.GridLines = true;                                    //グリッドラインの表示
            listView.HoverSelection = false;                            //ポイントで選択できるようにする
            listView.Activation = ItemActivation.OneClick;                //シングルクリック選択;
            listView.CheckBoxes = false;                                //チェックボックス無効化
            listView.View = View.Details;                                //リストビューの表示方法
            listView.AllowDrop = false;                                    //listViewへのドロップを受け入れない
            //イベントハンドラの追加
            listView.MouseDoubleClick+= new MouseEventHandler(ListView_DoubleClick);
            if(ListType == 1)    //CmdListの場合
            {
                listView.ColumnClick += new ColumnClickEventHandler(ListView_ColumnClick);
            }
            //ヘッダー定義
            ColumnHeader columnIndex = new ColumnHeader{Text = "Index", Width = 40};
            ColumnHeader columnCmdName = new ColumnHeader{Text = "命令セット名", Width = 100};
            ColumnHeader columnDescription = new ColumnHeader{Text = "説明", Width = 366};
            ColumnHeader[] colHeaderRegValue = {columnIndex, columnCmdName, columnDescription};    //ヘッダー設定
            listView.Columns.AddRange(colHeaderRegValue);    //ヘッダー追加
            //Tglに値がある場合リストビューに読み込む
            int n = Tgl.CountSets();
            if(n > 0)
            {
                for(int i = 0; i < n; i++)
                {
                    string[] item = {i.ToString(), Tgl.GetSet(i).Name, Tgl.GetSet(i).Description};
                    listView.Items.Add(new ListViewItem(item));
                }
            }
            //FormにListViewを追加
            this.Controls.Add(listView);
        }

        //終了時処理
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            DialogResult dr = MessageBox.Show("「" + this.Text + "」" + "を終了しますか?", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if(dr == DialogResult.No)
            {
                e.Cancel = true;
            }
        }

        //Addボタンがクリックされた時
        protected void OnClick_Add(object sender, EventArgs e)
        {

             //解説:引数typeにより追加の「仕方」が変わる。
            if(ListType == 1)        //CmdListの場合
            {
                //CmdSetDlgによる命令セットの作成
                CmdSetDlg csd = new CmdSetDlg();    //引数無し(新規作成)
                if(csd.ShowDialog(this) == DialogResult.OK)
                {
                    listView.BeginUpdate();            //描画停止
                    Tgl.AddSet(csd.Tgs);
                    int last_one = Tgl.CountSets() - 1;    //Tgl最後のTGSet == 最新の命令セット
                    string[] item = {last_one.ToString(), Tgl.GetSet(last_one).Name, Tgl.GetSet(last_one).Description};
                    listView.Items.Add(new ListViewItem(item));
                    listView.EndUpdate();            //描画再開
                }
                csd.Dispose();
            }
            else if(ListType == 2)    //ExeListの場合
            {
                //CmdListDlgによる単純選択
                CmdListDlg cld = new CmdListDlg(Tge, 0);
                if(cld.ShowDialog(this) == DialogResult.OK)
                {
                    listView.BeginUpdate();            //描画停止
                    Tgl.AddSet(Tge.CmdList.GetSet(cld.Selection));    //TgeのCmdListからDeep copyを追加する
                    int last_one = Tgl.CountSets() - 1;    //Tgl最後のTGSet == 最新の命令セット
                    string[] item = {last_one.ToString(), Tgl.GetSet(last_one).Name, Tgl.GetSet(last_one).Description};
                    listView.Items.Add(new ListViewItem(item));
                    listView.EndUpdate();            //描画再開
                }
                cld.Dispose();
            }
        }

        //Delボタンがクリックされた時
        protected void OnClick_Del(object sender, EventArgs e)
        {
            //選択された行を確認する
            if(listView.SelectedItems.Count == 0)
                MessageBox.Show("データが選択されていません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            //選択があり、CmdList、ExeListの直接編集であるので
            else if(ListType > 0)
            {
                DialogResult dr = MessageBox.Show("命令リストのソースデータが失われます。\r\n本当によろしいですか?", "確認",
                                    MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if(dr == DialogResult.Yes)
                {
                    int selected_index = listView.SelectedIndices[0];
                    listView.Items.RemoveAt(selected_index);
                    Tgl.RemoveAt(selected_index);
                }
            }
        }

        //Initボタンがクリックされた時
        protected void OnClick_Init(object sender, EventArgs e)
        {

             //解説:引数typeにより処理を変える。
            if(ListType == 1)        //tge.CmdList(命令セットライブラリー)→システム使用命令リスト
            {
                MessageBox.Show("命令リストライブラリーの消去はできません。", "禁止事項", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            else if(ListType == 2)    //tge.ExeList(実行命令セット)→個別ユーザーリスト
            {
                DialogResult dr = MessageBox.Show("命令リストのソースデータが失われます。\r\n本当によろしいですか?", "確認",
                                    MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if(dr == DialogResult.Yes)
                {
                    listView.Items.Clear();
                    Tgl.Clear();
                }
            }
        }

        //OKボタンがクリックされた時
        protected void OnClick_OK(object sender, EventArgs e)
        {
            //ListTypeが1、2の場合、CmdListまたはExeListを直接編集するので戻り値は無い
            if(ListType == 0)    //単純選択の場合のみ、Tgs(TGSet)を返す
            {
                //選択された行を確認する
                if(listView.SelectedItems.Count == 0)
                {
                    MessageBox.Show("データが選択されていません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
                else
                {
                    Selection = listView.SelectedIndices[0];    //CmdListのSelection番目のTGSet
                }
            }
            //このフォームの戻り値
            DialogResult = DialogResult.OK;
            Close();
        }

        //Cancelボタンがクリックされた時
        protected void OnClick_Cancel(object sender, EventArgs e)
        {
            Selection = -1;        //未選択
            //このフォームの戻り値
            DialogResult = DialogResult.Cancel;
            Close();
        }

        //listViewがダブルクリックされた時
        protected void ListView_DoubleClick(object sender, MouseEventArgs e)
        {
            //選択された項目があるか確認
            if(listView.SelectedIndices.Count > 0)
            {
                Selection = listView.SelectedIndices[0];
                //解説:引数typeにより処理が変わる。

                if(ListType == 0)        //命令セット選択
                {
                    DialogResult = DialogResult.OK;
                    Close();            //Selection設定のみで終了
                }
                else if(ListType == 1)    //命令セットライブラリー(CmdList)
                {
                    TGSet copy = new TGSet(Tgl.GetSet(Selection));    //編集用データは直接変更されないようにコピーを渡す
                    CmdSetDlg csd = new CmdSetDlg(copy);            //データコピーを使って編集
                    if(csd.ShowDialog(this) == DialogResult.OK)        //編集結果がOKなら
                    {
                        Tgl.GetSet(Selection).Set(csd.Tgs);            //編集結果をオリジナル命令セットに代入する
                        listView.SelectedItems[0].Text = Selection.ToString();
                        listView.SelectedItems[0].SubItems[1].Text = csd.Tgs.Name;
                        listView.SelectedItems[0].SubItems[2].Text = csd.Tgs.Description;
                        MessageBox.Show(Selection.ToString() + "番目の命令セットを編集しました。", "確認", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    csd.Dispose();
                }
            }
        }

        //listViewのコラムがクリックされた時
        private void ListView_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            //ListViewItemSorterを指定する
            listView.ListViewItemSorter = new ListViewItemComparer(e.Column);
            //並び替える(ListViewItemSorterを設定するとSortが自動的に呼び出される)
        }
    }


    ///////////////////////////////////////////
    //ListViewの項目の並び替えに使用するクラス
    ///////////////////////////////////////////

    public class ListViewItemComparer : IComparer
    {
        private int m_column;
        private static int m_order = 1;    //毎回呼ばれるたびに正順、逆順を交代させるフラグ

        //ListViewItemComparerクラスのコンストラクタ
        public ListViewItemComparer(int col)
        {
            m_column = col;
            m_order *= -1;    //ListViewItemComparerが呼ばれる度に正順、逆順が変更される
        }

        //xがyより小さいときはマイナスの数、大きいときはプラスの数、同じときは0を返す
        public int Compare(object x, object y)
        {
            //ListViewItemの取得
            ListViewItem itemx = (ListViewItem) x;
            ListViewItem itemy = (ListViewItem) y;
            //xとyを文字列として比較する
            return string.Compare(itemx.SubItems[m_column].Text, itemy.SubItems[m_column].Text) * m_order;
        }
    }

 

今日アップした本文を見て、すぐに朝令暮改しました。

 

オリジナルは「命令入力ダイアログ」でPenColorを選択すると「引数1」だけがカラー選択ダイアログで選べるようになり(またはキャンセルして手入力をするのですが)、

 

「繰り返し回数」による引数の変化を与えられませんでした。

 

これはいかん!

 

ということで、「命令入力ダイアログ」の引数2と引数3の".Enable3d = false;"の属性をカラー選択ダイアログ終了後、".Enable3d = true;"に戻し、色を選択するにせよ、キャンセルするにせよ、

(解説:↑はを選択した状態)

 

引数2、引数3による入力を解禁しました。これでループ中に色を変えることができます。具体的には、色情報はARGB(Alpha、Red、Green、Blue)が8bit0~255迄上位からARGBの形で並んでいるので、の場合は

 

 A-完全な不透明の場合、-1(0XFF)が入り、10進数では16,777,216(256X256X256)倍されます。

R-赤の場合-1(0XFF)が入り、10進数では65,536(256X256)倍されます。

Gー緑の場合-1(0XFF)が入り、10進数では256倍されます。

Bー青の場合-1(0XFF-10進数で255)が入ります。

= 0xFF0000FF16進数)

= -16,777,216 + 0 + 0 + 255=-16,776,961(上記ダイアログ値参照)

 

ということで、

 

今回の変更により、(例えば)引数2に与えるべき数は、

 

引数2=R部分の変更値x65,536倍G部分の変更値x256倍B部分の変更値

 

ということになります。面倒ですが、一応値を変更できるようになったので

 

お許しを!

 

ps. なお、先般アップした「ご参考」も本日修正しました。

 

                        case 11:            //PenColor(Color構造体←整数の変換-解説:Colorのメソッドです。)
                            Turtle.PenColor = Color.FromArgb(cmd[1] + cmd[2] * i + cmd[3] / (times - i));    //2026年04月22日変更
 

前回はTGEライブラリーのTurtleGraphics命令のデータ処理部分をやりましたので、今回はそのUI部分である「命令セットダイアログ(CmdSetDlg)」と「命令リストダイアログ(CmdListDlg)」をやりましょう。

 

復習になりますが、命令セットクラス(TGSet)のデータ部分は

    /////////////////////////////////////////////////
    //命令セットクラス(名称と説明付きの命令セット)
    /////////////////////////////////////////////////

    public class TGSet
    {    //クラスメンバー
        List<int[]> CmdSet;                        //命令配列
        public string Name {get; set;}            //命令セット名
        public string Description {get; set;}    //説明

(以下略)

 

命令リストクラス(TGList)のデータ部分は

    ///////////////////////////////////////////
    //命令リストクラス-命令セットの集合クラス
    ///////////////////////////////////////////

    public class TGList
    {
        //クラスメンバ
        List<TGSet> CmdList;
        public string FileName {get; set;}        //ファイル入出力名
(以下略)

 

のようになっていたことを念頭に以下解説します。

 

先ず「命令セットダイアログ」(表示は「命令セット入力ダイアログ」)で命令セットの作成を行う

には「命令追加」ボタンを押して命令を入力することが必要です。

 

命令追加」ボタンを押すと「入力ダイアログ(InputDlg)」(表示は「命令入力ダイアログ」)が現れるので、それで行います。

 

入力ダイアログ」の左にあるドロップダウンリストをプルダウンするとNopからDelayまでの命令が表示されるので、

 

例えばForwardを選択して引数を入力しようとすると引数の入力の際に引数の説明文が現れます。

 

引数が一つの殆どの命令はすべて同じ説明ですが、MoveTo

 

PenClolorだけ例外扱いとなります。特にPenColorは引数1のみが入力可能となり、入力しようとすると

 

カラー選択ダイアログが現れて数値入力を省略カラー選択ダイアログをキャンセルすると手入力が可能です)することができます。

 

命令の入力が終わる()と、

:この命令セットを繰り返す場合には、右の「繰り返し回数」のテキストボックスに回数を入力します。

 

命令・説明」のボタンを押して、専用入力画面()で入力します。「命令・説明」のボタンが変化した「命令セット」のボタンを押すと命令セット入力画面に戻ります。

:これは別のダイアログではなく、(Tabコントロールのように)同じダイアログのコントロールのVisible属性を弄ってこのように見せているだけです。

 

入力が終わるとその命令セットはTGEditクラスCmdList)に追加され(最下段参照)、それは(命令セットの追加、削除、編集が可能な)命令セットライブラリー」という表示のCmdListDlgで確認することができます。又、このダイアログは最上部のコラムをクリックすることでソートされたり、選択した行の命令セットをダブルクリックすると、

TGEditorが終了する際にこのライブラリー情報はCmdList.tgeというファイルに自動出力され、TGEditorを起動するたびに自動入力されます。

 

その命令セットが「命令セット編集ダイアログ」で編集可能となります。これは夫々の命令についても同じで、各命令をダブルクリックすると、

 

命令編集ダイアログ」が現れ、その命令を編集することができます。

 

(ご参考)両ダイアログとも「入力」モードで使用する場合、TGSetクラスインスタンスをnewにより新しく生成しますが(値渡し)、「編集」モードではTGEditクラスメンバーのTGListクラスインスタンスCTGSetクラスインスタンスを直接扱います。(参照渡し)

 

命令セットライブラリー」という表示のCmdListDlgは「描画部品」である命令セットのライブラリーの追加()、削除、編集を行います。

:↑で既に見た命令セット入力ダイアログ」が表示されるので、それで入力します。

 

命令セットライブラリー」の命令セット単体の実行は主にテスト目的で行われますが、「命令セット選択」という表示の「命令選択ダイアログ

 

で命令セットを選択して「OK」ボタンを押すか、ダブルクリックすると、「命令選択ダイアログ」の終了確認が出るので、終了させると実行されます。

 

CmdListDlgの「描画部品」である命令セットから選択したものを組み合わせて実行する場合には、「実行命令セット一覧

 

という表示のTGEditクラスの「実行リスト(ExeList))専用ダイアログを使います。このダイアログでは「命令セット追加」ボタンを押しても「命令セット入力ダイアログ」は現れず、↑の「命令選択ダイアログ」が出ますので、それでライブラリーから選択します。又ダブルクリックしても編集ダイアログはあられません。純粋にライブラリーからの選択、削除だけとなります。

:TGEditorの「ファイル」メニューの操作はこのExeListに対して行われます。従って特定のExeListをファイル(「実行ファイル」と言います)に(名前を付けて)保存したり、読み込んだりすることができます。ライブラリーファイルは自動保存、自動読み込みですが、実行ファイルユーザー管理で保存、自動読み込みします。

 

例えば↑の実行リストを実行すると、

 

となります。なお、「命令セットライブラリー」、「命令セット選択」、「実行命令セット一覧」という同じようなダイアログは(「命令セット入力・編集ダイアログ」、「命令入力・編集ダイアログ」と同様)同一ダイアログのコントロールや処理を制御して使い分けるようにしています。

 

繰り返しになりますが、メニューは、

 

ファイル」(実行ファイル関連操作)、

編集」(命令セット作成、命令リストによるライブラリー命令セットの作成、編集、削除、および命令リストによる実行リスト命令セットの選択、削除)、

実行」(命令選択ダイアログによる命令セット単体の実行、実行リストの実行)、

ヘルプ」(手抜きのメッセージボックス情報とバージョンダイアログが出ます)

 

で構成され、主要な処理はツールバーボタンで即実行できます。最下段のステータスバーにはバージョン情報と実行ファイルのファイルパスが表示されます。

 

前回と同様、コードは「ご参考」として後日アップします。