winforms 如何在文本更改后设置TextBox.SelectionStart?

yzxexxkh  于 2023-03-03  发布在  其他
关注(0)|答案(2)|浏览(101)

下面是我的代码:

private void textBox_TextChanged(object sender, EventArgs e)
{
    int selectionStart = textBox.SelectionStart;
    textBox.Text = new string(textBox.Text.Distinct().ToArray());
    textBox.Select(selectionStart, 0);
}

这段代码的工作原理如下:
1.如果我在 * textBox.Text * 的末尾插入一个新的唯一字符(字符串 * textBox.Text * 中没有的字符)
1.如果我试图在 * textBox.Text * 的末尾插入字符串 * textBox.Text * 中的字符
1.如果我在字符串 * textBox.Text * 中间插入一个新的唯一字符
但是当我尝试在字符串 * textBox.Text * 中间插入一个字符(即字符串 * textBox.Text * 中的字符)时,这段代码不能正常工作。选择光标向右移动,但它不应该向右移动,因为文本没有改变。

lb3vh1jj

lb3vh1jj1#

TextChanged事件无法禁止插入符号向右移动。这是它的默认行为。但是,您可以在TextChanged事件中添加一行代码并修改selectionStart值来进行补偿

private void textBox_TextChanged(object sender, EventArgs e)
{
    int selectionStart = textBox.SelectionStart;
    int cnt = textBox.Text.GroupBy(t => t).Any(x => x.Count() > 1) ? -1 : 0;
    textBox.Text = new string(textBox.Text.Distinct().ToArray());
    textBox.Select(selectionStart + cnt, 0);
}

关键行计算是否需要补偿插入符号的右移,首先对文本框中的字符进行分组,然后计数是否有任何组的计数大于1。如果是这种情况,则调整selectionStart变量以进行补偿。
正如你所发现的,这种方法在保持字符的原始位置上失败了。如果你试图在一个已经存在的字符之前插入一个已经存在的字符,上面的代码会保留第一个字符并删除最后一个字符。
如果要保留最后一个,则应使用KeyDown事件或KeyPress。

private void textBox_KeyDown(object sender, KeyEventArgs e)
{
    char c = (char)e.KeyValue;
    e.SuppressKeyPress = textBox.Text.Contains(c);
}

如果您还需要处理“粘贴”命令,则应编写自己的TextBox类,并在按CTRL+V或选择“粘贴”菜单时覆盖Windows API调用的WndProc方法

public class MyTextBox : TextBox
{
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x302 && Clipboard.ContainsText())
        {
            var pasteText = Clipboard.GetText().ToArray();
            var currText = this.Text.ToArray();
            var newText = pasteText.Except(currText).ToArray();
            Clipboard.SetText(new string(newText));
        }
        base.WndProc(ref m);
    }
}

当然,您需要向表单中添加MyTextBox的示例,而不是标准的TextBox。

9lowa7mx

9lowa7mx2#

试试看:

private void textBox_TextChanged(object sender, EventArgs e)
{
    int selectionStart = textBox.SelectionStart;
    int originalTextLength = textBox.Text.Length;
    textBox.Text = new string(textBox.Text.Distinct().ToArray());
    int lengthDif = originalTextLength - textBox.Text.Length;
    textBox.Select(selectionStart - lengthDif, 0);
}

基本上,它会检查原始输入文本的长度是否被修改(在删除额外字符之前),如果是,它会移动光标以补偿删除的字符。

相关问题