1

I have a very old software for which the source code is not available and I am not even sure what language was used to develop it. I am trying to replicate it using windows forms (C#).

I have stumbled at a feature that I have no clue how to replicate. The shown sketch below has small squares that can be selected with the mouse and moved using the arrow keys. The location of these squares are also linked to text boxes. If their locations are changed, the values in the text boxes will also change and vice-versa. In the images below, I pointed to one of the squares with a red arrow and boxed its corresponding text box with a red box.

Before movement:

Before movement of square

After movement:

After movement of square

I am not sure how this feature could be replicated. I am inclined to believe that these squares have to be separate objects on top of the sketch rather than being part of the sketch. In other words, one would need to create a custom winform control that can be selected with the mouse and moved with the arrow keys. Am I thinking in the right direction or is there any better way to tackle this problem? If this is the right approach then how do I go about creating a custom control having such properties?

1
  • They look like plain checkboxes to me, so i'd expect a control array, and you can 'move' controls on Winforms, with the the top/left properties and some redraw. If that green box is at the top left of the UI, it will make it easier as the checkbox postion will absolute rather than needing any offsets :)
    – cjb110
    Commented Jun 17 at 8:35

1 Answer 1

1

Assuming those little squares are colored buttons, I implemented the feature you mentioned. With little modification you could achieve the same. Here is an image of a simple form that I created to implement the feature asked

The three red buttons are selectable and become green when clicked and can be moved with the arrow key when selected. There is no out of bound logic implementation, but it could easily be made. The code written to make it easily understood, so no size optimization was made. Here is the code implementation for Form1:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private List<Button> buttonList = new List<Button>();
        private List<TextBox> textboxList = new List<TextBox>();
        public Form1()
        {
            InitializeComponent();
            this.KeyPreview = true;
            buttonList.Add(button1);
            buttonList.Add(button2);
            buttonList.Add(button3);
            textBox1.Text = button1.Location.ToString();
            textBox2.Text = button2.Location.ToString();
            textBox3.Text = button3.Location.ToString();
            textboxList.Add(textBox1);
            textboxList.Add(textBox2);
            textboxList.Add(textBox3);
            buttonList.ForEach(button =>
            {
                button.PreviewKeyDown += new PreviewKeyDownEventHandler(button_PreviewKeyDown);
                button.LocationChanged += new EventHandler(OnButtonLocationChange);
            });
            this.KeyDown += new KeyEventHandler(Form1_KeyPress);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            button_logic(sender, e);
        }
        private void OnButtonLocationChange(object sender, EventArgs e)
        {
            textboxList[buttonList.IndexOf((Button)sender)].Text = ((Button)sender).Location.ToString();
        }
        private void Form1_KeyPress(object sender, KeyEventArgs e)
        {
            if (buttonList.FirstOrDefault(x => x.BackColor == Color.Green) == null)
                return;
            if (e.KeyCode == Keys.Up)
            {
                Button tempButton = buttonList.First(x => x.BackColor == Color.Green);
                buttonList.First(x => x.BackColor == Color.Green).Location = new Point(tempButton.Location.X, tempButton.Location.Y - 10);
            }
            else if (e.KeyCode == Keys.Down)
            {
                Button tempButton = buttonList.First(x => x.BackColor == Color.Green);
                buttonList.First(x => x.BackColor == Color.Green).Location = new Point(tempButton.Location.X, tempButton.Location.Y + 10);
            }
            else if (e.KeyCode == Keys.Left)
            {
                Button tempButton = buttonList.First(x => x.BackColor == Color.Green);
                buttonList.First(x => x.BackColor == Color.Green).Location = new Point(tempButton.Location.X - 10, tempButton.Location.Y );
            }
            else if (e.KeyCode == Keys.Right)
            {
                Button tempButton = buttonList.First(x => x.BackColor == Color.Green);
                buttonList.First(x => x.BackColor == Color.Green).Location = new Point(tempButton.Location.X + 10, tempButton.Location.Y);
            }
        }
        private void button_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            var keys = new[] { Keys.Left, Keys.Right, Keys.Up, Keys.Down };
            if (keys.Contains(e.KeyData))
                e.IsInputKey = true;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            button_logic(sender, e);
            this.Focus();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            button_logic(sender, e);
        }
        private void button_logic(object sender, EventArgs e)
        {
            foreach(Button button in buttonList)
            {
                if((Button)sender == button)
                {
                    button.BackColor = Color.Green;
                }
                else
                {
                    button.BackColor = Color.Red;
                }
            }
            this.Focus();
        }
    }
}

1
  • 1
    Thanks Nathan. I ended up creating a custom panel control that's selectable and movable with the arrow keys but your answer is very interesting as well. It is still missing the reverse where the location of the button changes if the textbox content changes but that shouldn't be hard to implement. With some custom painting of the buttons I should be able to reach what I want from your answer. Thanks again. Commented Jun 22 at 2:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.