简体   繁体   中英

Limit multiple textbox to number

I found the following solution to limit textbox to numbers. I have 20 textBoxes in my GUI is there a cleaner way than making 20 of these functions?

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
 {
        e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);
 }

My suggestion is to replace the standard TextBox Controls that need this feature, with a Custom Control that can also filter the User input when text is pasted in the Control or when the Control's Text Property is set in the Designer, using the PropertyGrid.

If you only handle the KeyPress event, you cannot prevent a bad paste.
I think it's also better to filter what is set in the Text Property, to avoid a misunderstanding .

Test this simple Custom TextBox Control: it handles direct User input and text pasted at run-time. Setting the UserPaste Property to Disallow , pastes are ignored, while setting it to NumbersOnly (default) allows just numbers: if mixed chars are pasted in the Control, only the numbers are preserved.

To also allow the input of comma and dot, change the Regex in [^0-9,.\b] .

The Text property set in the Designer is also filtered.

To replace the existing TextBox Controls with the this Custom Control, you can use the Find/Replace function (usually activated with CTRL+H ) in Visual Studio:

using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Windows.Forms;

[ToolboxItem(true)]
[DesignerCategory("Code")]
public class TextBoxNumbers : TextBox
{
    private Regex regex = new Regex(@"[^0-9\b]", RegexOptions.Compiled);

    public TextBoxNumbers() { }

    public override string Text {
        get => base.Text;
        set { if (!base.Text.Equals(value)) base.Text = regex.Replace(value, ""); }
    }

    public enum PasteAction {
        NumbersOnly,
        Disallow
    }

    [DefaultValue(PasteAction.NumbersOnly)]
    public PasteAction UserPaste { get; set; }

    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        if (regex.IsMatch(e.KeyChar.ToString())) {
            e.Handled = true;
        }
        base.OnKeyPress(e);
    }

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg) {
            case NativeMethods.WM_PASTE:
                switch (UserPaste) {
                    case PasteAction.Disallow:
                        return;
                    case PasteAction.NumbersOnly:
                        string text = Clipboard.GetText(TextDataFormat.UnicodeText);
                        text = regex.Replace(text, "");
                        NativeMethods.SendMessage(this.Handle, NativeMethods.EM_REPLACESEL, 1, text);
                        return;
                }
                break;
        }
        base.WndProc(ref m);
    }
}

NativeMethods class:

using System.Runtime.InteropServices;

private class NativeMethods
{
    internal const int WM_PASTE = 0x0302;
    internal const int EM_REPLACESEL = 0xC2;

    [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    internal static extern int SendMessage(IntPtr hWnd, uint uMsg, int wParam, string lParam);
}

My simple and go-to solution would be to wirte the methode once, after that go to the desginer and select every of your texboxes that need it, click on the event-button in the propperties, scroll to the KeyPress Event and click on it once, now a dropdown-arrow should apear, select your methode there - done.

private void textBox_KeyPress(object sender, KeyPressEventArgs e)
 {
     e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM