在winforms文本框控件中解析用户输入

本文关键字:用户 输入 控件 winforms 文本 | 更新日期: 2023-09-27 18:02:39

我正在尝试创建某种类型的许可验证文本框,自动将用户输入分割成由连字符分隔的块。我的许可证有25个字符长,它像这样分开:

XXXXX-XXXXX-XXXXX-XXXXX-XXXXX

我已经提出了以下代码来解析用户输入,而他是打字或通过复制/粘贴处理文本框控件的TextChanged事件,像这样:

public static string InsertStringAtInterval(string source, string insert, int interval)
        {
            StringBuilder result = new StringBuilder();
            int currentPosition = 0;
            while (currentPosition + interval < source.Length)
            {
                result.Append(source.Substring(currentPosition, interval)).Append(insert);
                currentPosition += interval;
            }
            if (currentPosition < source.Length)
            {
                result.Append(source.Substring(currentPosition));
            }
            return result.ToString();
        }
        private bool bHandlingChangeEvent = false;
        private void txtLicense_TextChanged(object sender, EventArgs e)
        {
            if (bHandlingChangeEvent == true)
                return;
            bHandlingChangeEvent = true;
            string text = txtLicense.Text.Replace("-", "").Replace(" ","");
            int nPos = txtLicense.SelectionStart;
            if((text.Length==5||text.Length==10||text.Length==15||text.Length==20) && txtLicense.Text[txtLicense.Text.Length-1]!='-')
            {
                txtLicense.Text += "-";
                txtLicense.SelectionStart = nPos + 1;
            }
            if(text.Length>=25)
            {
                string tmp = text.Substring(0, 25);
                tmp = InsertStringAtInterval(tmp, "-", 5);
                txtLicense.Text = tmp;
                txtLicense.SelectionStart = nPos;
            }

            bHandlingChangeEvent = false;
        }

当我在框内键入和粘贴时,这是完美的。我唯一的问题是,当用户试图通过按退格键或delete键从输入键中删除字符时。

由于强制连字符插入@位置5,10,15,20,一旦用户到达退格键上的这些标记之一,上述逻辑强制将连字符添加到字符串中,并且用户不能超过此值。

我试着摆弄KeyDown事件,但没能想出任何有用的东西。有人能帮帮忙吗?

我也试过使用一个MaskedTextbox,但那东西是丑陋的,因为我不希望蒙版/连字符在焦点上可见,我当然不想用空白替换提示符,因为它会给一些混乱时,点击框内的光标将不总是定位在框的开始,当它"据说"空

在winforms文本框控件中解析用户输入

这些年来,这类事情给我带来了很多痛苦。我处理它的方法是对待文本的每次更改,就像从头开始粘贴一样——我去掉连字符,然后把它们放回适当的位置。然后,您可以处理用户删除最后一个字符的特殊情况。在本例中,将TextChanged事件之前的文本与之后的文本进行比较。如果它们是相同的,但是前一个文本长一个字符,就不要做任何特殊的操作。

这里是一些代码,似乎工作的文本输入,剪切/复制/粘贴等。它可以通过一些花哨的LINQ,一些错误处理等来改进,但希望它能理解这个想法。

private string previousText = string.Empty;
private bool processing = false;
private void textBox1_TextChanged(object sender, EventArgs e)
{
    // If we're already messing around with the text, don't start again.
    if (processing)
        return;
    processing = true;
    // The current textbox text
    string newText = textBox1.Text;
    // What was there before, minus one character.
    string previousLessOne = previousText == string.Empty ? string.Empty : previousText.Substring(0, previousText.Length - 1);
    // Get where the user is, minus any preceding dashes
    int caret = textBox1.SelectionStart - (textBox1.Text.Substring(0, textBox1.SelectionStart).Count(ch => ch == '-'));
    // If the user has done anything other than delete the last character, ensure dashes are placed in the correct position.
    if (newText.Length > 0 && newText != previousLessOne)
    {
        textBox1.Text = string.Empty;
        newText = newText.Replace("-", "");
        for (int i = 0; i < newText.Length; i += 5)
        {
            int length = Math.Min(newText.Length - i, 5);
            textBox1.Text += newText.Substring(i, length);
            if (length == 5)
                textBox1.Text += '-';
        }
    }
    // Put the user back where they were, adjusting for dashes.
    textBox1.SelectionStart = caret + (caret / 5);
    previousText = textBox1.Text;
    processing = false;
}

你可以试试这个版本:

void txtLicense_KeyDown(object sender, KeyEventArgs e) {
  if (e.KeyCode == Keys.Back) {
    int index = txtLicense.SelectionStart;
    while (index > 0 && txtLicense.Text[index - 1] == '-') {
      --index;
    }
    if (index > 0) {
      --index;
    }
    txtLicense.Select(index, txtLicense.SelectionLength + Math.Max(index, 1));
    txtLicense.SelectedText = string.Empty;
    e.SuppressKeyPress = true;
  }
}

我以前做过类似的事情。我要做的是不添加连字符,直到它的插入点后有一个字符。例如,不要在输入5个字符后添加连字符,而是在输入6个字符时添加连字符,这样就不会在末尾添加连字符。

下面是我用来在特定位置插入连字符的算法:

public static string FormatLicenseNumber(string str)
{
    if (string.IsNullOrEmpty(str))
        return str;
    else
    {
        str = str.Replace("-", string.Empty);
        if (str.Length > 20)
            str = str.Insert(20, "-");
        if (str.Length > 15)
            str = str.Insert(15, "-");
        if (str.Length > 10)
            str = str.Insert(10, "-");
        if (str.Length > 5)
            str = str.Insert(5, "-");
        return str;
    }
}