2019年9月7日土曜日

C# グリッド状に配置したTextBoxをカーソルキーで移動したい!

必要に駆られて書いたので覚書
もっとかんたんなほうほうあるんやろか


public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        List textBoxList = new List();

        private void Form1_Load(object sender, EventArgs e)
        {
            foreach (var item in this.Controls)
            {
                if (item is TextBox) textBoxList.Add(item as TextBox);
            }

            textBoxList.ForEach(x => x.KeyDown += X_KeyDown);
            textBoxList.ForEach(x => x.Text = "hogehoge");
        }

        private void X_KeyDown(object sender, KeyEventArgs e)
        {
            var t = sender as TextBox;
            TextBox nextControl;
            switch (e.KeyCode)
            {
                case Keys.Left:
                    if (t.SelectionStart != 0 && t.SelectionLength != t.Text.Length) return;//文字列編集途中なら抜ける

                    nextControl = textBoxList.Where(x => t.Location.X - 5 > x.Location.X)
                        .OrderBy(x => getDistance(t.Location.X, t.Location.Y, x.Location.X, x.Location.Y)).FirstOrDefault();

                    if (nextControl != null)
                    {
                        nextControl.Focus();
                        nextControl.SelectAll();
                    }

                    break;
                case Keys.Up:
                    nextControl = textBoxList.Where(x => t.Location.Y - 5 > x.Location.Y)
                        .OrderBy(x => getDistance(t.Location.X, t.Location.Y, x.Location.X, x.Location.Y)).FirstOrDefault();

                    if (nextControl != null)
                    {
                        nextControl.Focus();
                        nextControl.SelectAll();
                    }
                    break;
                case Keys.Right:
                    if (t.SelectionStart != t.TextLength  && t.SelectionLength != t.Text.Length) return;//文字列編集途中なら抜ける
                    
                    nextControl = textBoxList.Where(x => t.Location.X + 5 < x.Location.X)
                        .OrderBy(x => getDistance(t.Location.X, t.Location.Y, x.Location.X, x.Location.Y)).FirstOrDefault();

                    if (nextControl != null)
                    {
                        nextControl.Focus();
                        nextControl.SelectAll();
                    }
                    break;
                case Keys.Down:
                    nextControl = textBoxList.Where(x => t.Location.Y + 5 < x.Location.Y)
                        .OrderBy(x => getDistance(t.Location.X, t.Location.Y, x.Location.X, x.Location.Y)).FirstOrDefault();

                    if (nextControl != null)
                    {
                        nextControl.Focus();
                        nextControl.SelectAll();
                    }
                    break;
            }

        }

        private double getDistance(double x1, double y1, double x2, double y2)
        {
            return Math.Sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
        }
    }







最初からDataGrid系のコントロールを使えばよかった・・・