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.