C# 将用户输入解析为winforms Textbox控件中的用户类型

C# 将用户输入解析为winforms Textbox控件中的用户类型,c#,winforms,C#,Winforms,我正在尝试创建某种许可证验证文本框,自动将用户输入分割成由连字符分隔的块。我的许可证长度为25个字符,按如下方式分开: XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX 我已经想出了以下代码来解析用户在键入时的输入,或者通过复制/粘贴来处理Textbox控件的TextChanged事件,如下所示: public static string InsertStringAtInterval(string source, string insert, int interval)

我正在尝试创建某种许可证验证文本框,自动将用户输入分割成由连字符分隔的块。我的许可证长度为25个字符,按如下方式分开:

XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX

我已经想出了以下代码来解析用户在键入时的输入,或者通过复制/粘贴来处理Textbox控件的
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;
        }
公共静态字符串InsertStringAtInterval(字符串源、字符串插入、整数间隔)
{
StringBuilder结果=新建StringBuilder();
int currentPosition=0;
while(当前位置+间隔<源长度)
{
结果.Append(source.Substring(currentPosition,interval)).Append(insert);
当前位置+=间隔;
}
if(当前位置<源长度)
{
result.Append(source.Substring(currentPosition));
}
返回result.ToString();
}
private bool bHandlingChangeEvent=false;
私有void txtLicense_TextChanged(对象发送方,事件参数e)
{
if(bHandlingChangeEvent==true)
返回;
bHandlingChangeEvent=true;
字符串text=txtLicense.text.Replace(“-”,”).Replace(“,”);
int nPos=txtLicense.SelectionStart;
如果((text.Length==5 | | | text.Length==10 | | | text.Length==15 | | text.Length==20)和&txtLicense.text[txtLicense.text.Length-1]!='-'))
{
txtLicense.Text+=“-”;
txtLicense.SelectionStart=nPos+1;
}
如果(文本长度>=25)
{
字符串tmp=text.Substring(0,25);
tmp=插入字符串间隔(tmp,“-”,5);
Text=tmp;
txtLicense.SelectionStart=nPos;
}
bHandlingChangeEvent=false;
}
当我在框内输入并粘贴用户时,这项功能可以完美地工作。我唯一的问题是,当用户试图通过按backspace或delete从输入的键中删除字符时

由于强制连字符插入@位置5,10,15,20,一旦用户在退格键上达到其中一个标记,则上述逻辑将强制将连字符添加到字符串中,并且用户不能超出该范围

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


我也尝试过使用MaskedTextbox,但这很难看,因为我不想让遮罩/连字符在焦点上可见,我当然不想将提示替换为空白,因为在框内单击时会产生一些混乱,因为光标在“假定”时不会始终位于框的开头空。

您可以尝试此版本:

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

这些年来,这类事情给我带来了很多痛苦。我的方法是将文本的每一个更改都视为是从头粘贴的—我去掉连字符,然后将它们放回适当的位置。然后,您可以处理用户删除最后一个字符的特殊情况。在本例中,您将比较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;
}
private string previousText=string.Empty;
私有布尔处理=假;
私有void textBox1\u TextChanged(对象发送方,事件参数e)
{
//如果我们已经把课文弄乱了,就不要再开始了。
如果(处理)
返回;
处理=真;
//当前文本框文本
字符串newText=textBox1.Text;
//之前是什么,减去一个字符。
字符串previousLessOne=previousText==string.Empty?string.Empty:previousText.Substring(0,previousText.Length-1);
//获取用户所在的位置,减去前面的任何破折号
int caret=textBox1.SelectionStart-(textBox1.Text.Substring(0,textBox1.SelectionStart.Count)(ch=>ch='-');
//如果用户除了删除最后一个字符外还执行了其他操作,请确保将破折号放置在正确的位置。
如果(newText.Length>0&&newText!=上一篇课文)
{
textBox1.Text=string.Empty;
newText=newText.Replace(“-”,”);
对于(int i=0;i
会有帮助吗?我刚刚编辑了关于这个问题的问题,因为我想有人会提到它。。检查我的报告的结尾question@DJKRAZE不确定你的目标是什么。。我很高兴我不是第一个想这么做的人