如何限制文本框只接受特定字符

3
我想知道如何在c#表单应用程序中限制文本框中特定字符的数量。 例如,我希望限制用户仅能输入一个减号(minus),如果用户尝试再次输入,则程序将禁止其再次输入。
示例:-123、123-或123-123(只有一个减号)。
如果用户删除了减号,则应该允许重新输入一个减号,当然不能再输入更多!
我想防止用户输入----1234、1234--、123-4--21或其他更多的内容!!
以下是我的尝试:
private void txtStopAfterXTimes_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.OemMinus || e.KeyCode == Keys.Subtract)
    {
        if (txtStopAfterXTimes.Text.Count((char)'-', 1))
        {
            e.SuppressKeyPress = true;
        }
        else if (txtStopAfterXTimes.Text.Count((char)'-', 0))
        {
            e.SuppressKeyPress = false;
        }
    }
}

我知道这是不对的,但请帮帮我!谢谢...


2
e.SuppressKeyPress = txtStopAfterXMinutes.Text.Count(c => c == '-') > 0 - vasily.sib
抱歉,我在帖子中有错误,所以我进行了编辑! - hamidrezas120
我尝试过:e.SuppressKeyPress = txtStopAfterXTimes.Text.Count(c => c == '-') > 0; 但是没有起作用。您能否描述一下您的代码是做什么的? - hamidrezas120
它在 txtStopAfterXMinutes.Text 中计算 - 字符数,如果超过0个,则将 e.SuppressKeyPress 设置为false。 - vasily.sib
我会使用类似于这样的东西(https://stackoverflow.com/a/53681247/3110834),因为您需要考虑粘贴。 - Reza Aghaei
2个回答

3
您可以通过两种方式更改txtStopAfterXTimes中的Text:按下键 (-) 或者粘贴数值。
因此,我们需要处理两个事件KeyPress 用于处理按下 - 键的情况,TextChanged 用于处理文本粘贴事件。 代码: (WinForms)
private void txtStopAfterXTimes_TextChanged(object sender, EventArgs e) {
  // When pasting a text into txtStopAfterXTimes...
  TextBox box = sender as TextBox;

  StringBuilder sb = new StringBuilder(box.Text.Length);

  bool containsMinus = false;

  // We remove all '-' but the very first one
  foreach (char ch in box.Text) {
    if (ch == '-') {
      if (containsMinus)
        continue;

      containsMinus = true;
    }

    sb.Append(ch);
  }

  box.Text = sb.ToString();
}

private void txtStopAfterXTimes_KeyPress(object sender, KeyPressEventArgs e) {
  TextBox box = sender as TextBox;

  // we allow all characters ...
  e.Handled = e.KeyChar == '-' &&             // except '-'
              box.Text.Contains('-') &&       // when we have '-' within Text
             !box.SelectedText.Contains('-'); // and we are not going to remove it
}

抱歉,我的编程水平不如你,所以我有些困惑!:| 如果可能的话,你能否给我更简单的方法?谢谢你的帮助,但我想知道两种方法,谢谢。 - hamidrezas120
处理两个事件而不是一个? - vasily.sib
抱歉,请问您能描述一下这段代码吗:foreach (char ch in box.Text) { 如果(ch == '-') { 如果(containsMinus) 继续; containsMinus = true; }sb.Append(ch); } 我的意思是它是如何工作的... - hamidrezas120
@hamidrezas120:我们扫描粘贴的文本(box.Text),如果我们得到了 -ch == '-'),我们应该决定是还是跳过它(continue)。如果我们之前已经取了 -if (containsMinus)),我们就省略这个减号;如果这是第一个 -,我们就取它,但标记一下(containsMinus = true;)我们有 -,并且我们应该跳过所有其他的减号。 - Dmitry Bychenko
最后一个问题:continue;会跳过整个foreach循环?还是指if(ch ==' - ')?或者是指if(containsMinus) - hamidrezas120
显示剩余9条评论

0

我建议避免使用 TextChanged,因为它会在文本更改后触发,可能有点晚。

这是我将要使用的解决方案,因为你还需要关心粘贴。

  • keyPress 中,我检查字符是否不是第一个“-”,如果是,则忽略它,否则接受它。
  • WndProc 中,我捕获 WM_PASTE 并清理剪贴板文本,删除除第一个以外的所有“-”出现。您还可以轻松决定在输入不可接受时停止粘贴。

以下是实现:

using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyTextBox : TextBox
{
    private const int WM_PASTE = 0x0302;
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern bool MessageBeep(int type);
    protected override void WndProc(ref Message m)
    {
        if (m.Msg != WM_PASTE) { base.WndProc(ref m); }
        else {
            //You can sanitize the input or even stop pasting the input
            var text = SanitizeText(Clipboard.GetText());
            SelectedText = text;
        }
    }
    protected virtual string SanitizeText(string value)
    {
        if (Text.IndexOf('-') >= 0) { return value.Replace("-", ""); }
        else {
            var str = value.Substring(0, value.IndexOf("-") + 1);
            return str + value.Substring(str.Length).Replace("-", "");
        }
    }
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        if (e.KeyChar == '-' && this.Text.IndexOf('-') >= 0) {
            e.Handled = true;
            MessageBeep(0);
        }
        else {
            base.OnKeyPress(e);
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接