簡體   English   中英

如何在 TextChanged 之后設置 TextBox.SelectionStart?

[英]How to set TextBox.SelectionStart after TextChanged?

這是我的代碼:

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 中的字符)
  2. 如果我嘗試在 textBox.Text 末尾插入字符串 textBox.Text 中的字符
  3. 如果我在字符串 textBox.Text 的中間插入一個新的唯一字符

但是,當我嘗試在字符串 textBox.Text 的中間插入一個字符(即在字符串 textBox.Text 中)時,此代碼無法正常工作。 選擇 cursor 向右移動,盡管它不應該向右移動,因為文本沒有改變。

試一試:

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);
    }

基本上它檢查長度是否從原始輸入的文本中修改(在刪除額外字符之前)。 如果是,它會移動 cursor 以補償刪除的任何字符。

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 變量以進行補償。

正如您所發現的,這種方法無法將字符保留在其原始 position 中。 如果您嘗試在已經存在的字符之前插入現有字符,則上面的代碼會保留第一個字符並刪除最后一個字符。

如果要保留最后一個,則應使用 KeyDown 事件或 KeyPress。

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

And if you need to process also the Paste command then you should write your own TextBox class and override the WndProc method called by the Windows API when you press CTRL+V or select the Paste menu

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 的實例添加到 forms 而不是標准的 TextBox。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM