Lee Yi
Lee Yi

Reputation: 527

C# Make a group of characters in a textbox behave like one character

Basically, I have keywords like sin( and cos( in a textbox, which I want to have behave like a single character.

When I mention the entire string below it is referring to the group of characters (for example "sin(")

Using sin( as an example:

If the caret was in this position (behind the s):

enter image description here

If you pressed del, it would remove the entire string. If the right arrow key was pressed the caret would jump to after the (.

If the caret was in this position (after the ():

enter image description here

If backspace was pressed, the entire string would be removed. If the left arrow key was pressed, the caret would jump to behind the s.

EDIT: Thanks to John Skeet who pointed this out.

Selecting any substring of the group of characters (for example si from sin() should select the entire string.

Sorry if it is difficult to understand, what I have in mind is a bit difficult to put into words.

EDIT 2: Thanks to Darksheao for providing me the answer for the backspace and delete keys. I relocated the delete segment to the PreviewKeyDown event, as it does not work with the KeyPress Event.

EDIT 3: Using the charCombinations way of doing things, here is how I did the implementation for the left and right keys:

#region Right
case Keys.Right:
{
    s = txt.Substring(caretLocation);
    foreach (string combo in charCombinations)
    {
       if (s.StartsWith(combo))
       {
            textBox1.SelectionStart = caretLocation + combo.Length - 1;
            break;
        }
    }
    break;
}
#endregion
#region Left
case Keys.Left:
    {
        s = txt.Substring(0, caretLocation);
        foreach (string combo in charCombinations)
        {
            if (s.EndsWith(combo))
            {
                textBox1.SelectionStart = caretLocation - combo.Length + 1;
                break;
            }
        }
        break;
    }
#endregion

All that remains is the mouse implementation. Anyone? I also realised that the user may use the mouse to place the caret in the middle of one of these strings, so when that happens the mouse needs to be moved to the start of the string.

Upvotes: 8

Views: 515

Answers (1)

Darksheao
Darksheao

Reputation: 114

Here is a section of code that sets up an array of the character combinations that you want to be seen as "single characters" and sets up a handler that looks for them.

private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
    string[] charCombinations = new string[2];
    charCombinations[0] = "sin(";
    charCombinations[1] = "cos(";
    string txt = this.textBox1.Text;
    int caretLocation = this.textBox1.SelectionStart;
    if (e.KeyCode == Keys.Delete)
    {
        //get text in front
        string s = txt.Substring(caretLocation);
        string notChecking = txt.Substring(0, caretLocation);
        foreach (string combo in charCombinations)
        {
            if (s.StartsWith(combo))
            {
                txt = notChecking + s.Substring(combo.Length - 1);
                break;
            }
        }
    }
    if (e.KeyCode == Keys.Back)
    {
        //get text in behind
        string s = txt.Substring(0, caretLocation);
        string notChecking = txt.Substring(caretLocation);
        foreach (string combo in charCombinations)
        {
            if (s.EndsWith(combo))
            {
                txt = s.Substring(0, s.Length - combo.Length + 1) + notChecking;
                caretLocation -= combo.Length - 1;
                break;
            }
        }
    }
    this.textBox1.Text = txt;
    //changing the txt feild will reset caret location
    this.textBox1.SelectionStart = caretLocation;
}

Making some modifications to this so that you are searching around the SelectionStart will handle what was mentioned in Jon's comment.

References: TextBox Event Reference and How do I find the position of a cursor in a text box? C#

Upvotes: 2

Related Questions