2013-03-06 76 views
2

我想创建某种类型的许可证验证文本框,自动将用户输入拆分为由连字符分隔的块。我的执照是25个字符长,而且分开,例如:解析用户输入作为用户键入WinForms文本框控件

XXXXX-XXXXX-XXXXX-XXXXX-XXXXX

我想出了下面的代码来分析用户的输入,而他是打字或通过复制/粘贴通过处理TextChanged事件TextBox控件像这样的:

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

虽然这是正常使用时,我的用户类型和箱内膏。我唯一的问题是,当用户试图通过按退格键或删除键从输入的键中删除字符时。

由于强制连字符插入@位置5,10,15,20,一旦用户在退格按下这些标记之一时,按上述逻辑强制连字符添加到字符串,并且用户不能超出该范围。

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

我也尝试过使用MaskedTextbox,但那件事很丑陋,因为我不想让遮罩/连字符在焦点上可见,我当然不想用空格替换提示,因为它会给一些混淆当在盒子内部点击时,由于当其“假定”为空时,光标不会始终位于盒子的开始处。

+1

会[MaskedTextBox](http://msdn.microsoft.com/en-us/library/system.windows.forms.maskedtextbox.aspx)有帮助吗? – publicgk 2013-03-06 15:23:39

+0

我刚刚编辑了我关于那个问题,因为我以为有人会提到它..检查我的问题的结束 – 2013-03-06 15:24:13

+0

@DJKRAZE不知道你在瞄准什么..你能在代码中解释也许 – 2013-03-06 17:32:43

回答

2

这样的事情已经有很多多年来为我痛苦的原因。我接近它的方式是将文本中的每个更改都视为从头开始粘贴 - 我将连字符去掉,然后将它们放回到适当的位置。然后,您可以处理用户删除最后一个字符的特殊情况。在这种情况下,您将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; 
} 
2

你可以试试这个版本:类似这样的前

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

我已经做了一些。我要做的就是在插入点后面有一个字符之前不要添加连字符。例如,不要在输入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; 
    } 
}