Home > Mobile >  How can I find the character at my caret position?
How can I find the character at my caret position?

Time:01-06

I'm trying to make a program similar to notepad. I want to make it so that when you type in a textbox, an opened curly brace would turn into an opened and a closed curly brace.

I just need the if statement to work properly.

if(textBox1.Text[textBox1.SelectionStart] == '{')
{
  //Removes the last {
  textBoxList.Clear();
  for(int i = 0; i < textBox1.TextLength - 2; i  )
  {
    textBoxList.Add(Convert.ToString(textBox1.Text[i]));
  }
  textBox1.Text = "";
  for(int i = 0; i < textBoxList.Count; i  )
  {
    textBox1.Text  = textBoxList[i];
  }
  //Adds the new curly braces
  textBox1.Text  = indentCurlyBraces;
  //Goes inside the if
  textBox1.SelectionStart = textBox1.TextLength - 2;
  textBox1.ScrollToCaret();
}

This if statement is inside of the textbox changed method.

I have tried using textBox1.SelectionStart, but the program crashes because the index is outside of the textBox1 string[] I also have tried subtracting one, two, adding things to the SelectionStart, but everything is still outside the bounds of the array.

CodePudding user response:

Copy this utility class in your solution:

public class TweakTextBox
{
    private readonly string _addValue;

    private readonly string _findValue;

    private readonly TextBox _textBox;

    private bool enable;

    public TweakTextBox(TextBox t, string findValue, string addValue)
    {
        _textBox = t;
        _findValue = findValue;
        _addValue = addValue;
        _textBox.TextChanged  = TextChanged;
        _textBox.PreviewKeyDown  = PreviewKeyDown;
    }

    private void PreviewKeyDown(object? sender, PreviewKeyDownEventArgs e) // this is required to allow backspacing on "}"
    {
        if (e.KeyCode == Keys.Back)
            enable = false; // disable the tweak in order to get the backspace working
        else
            enable = true; // replace the tweak functionality
    }

    private void TextChanged(object? sender, EventArgs e)
    {
        int index = _textBox.SelectionStart - 1; // find current position before char input = current SelectionStart - 1
        if (index >= 0 && (enable)) // if index is valid
        {
            string p = _textBox.Text[index..(index   1)]; // get last input char
            if (p == _findValue) // if found char is the one specified (e.g. "{")
            {
                string pre = _textBox.Text[0..index]; // get all text preceding the found char
                string post = _textBox.Text[(index   1)..]; // get all text following the found char
                _textBox.Text = pre   _findValue   _addValue   post; // final text is = previous text   found char   char to add   following text
                _textBox.Select(index   1, 0); // reposition the caret at the last user's position
            }
        }
    }
}

You just need to create an instance for each TextBox in which you would like to enable that function. Usage example:

public Form1()
{
    InitializeComponent();
    TweakTextBox tweak = new(textBox1, "{", "}"); // add this line in your Form constructor
    // add here other textboxes if you want
}

I added the PreviewKeyDown event, which disables the functionality if backspace is pressed: if you try disabling this event and backspacing with the caret after an automatically added "}" sign, you'll understand why I added this.

I'm sure there are more efficient ways to achive this - probably with WPF I'd use a different approach, but the question is tagged WinForms so I assume you are not using WPF.

Also, I didn't use KeyPress event because text could have changed for other reasons - I really think TextChanged is your desired event.

  • Related