Input only digits and control buttons - c#

I want to input Salary with any value: 550,49, 2222,12, 9,3 and so on. But need to use control button like this: ,, backspace, ctrl + c, ctrl + v, ctrl + a.
Salary is TextBox with ShortcutsEnabled = true and event:
private void TbSalary_KeyPress(object sender, KeyPressEventArgs e)
{
char number = e.KeyChar;
if ((e.KeyChar <= 47 || e.KeyChar >= 58) && number != 8 && number != 44)
//digits, BackSpace and ,
{
e.Handled = true;
}
}
If remove this condition, the specified combinations will work. But not only numbers are entered.
Should I add tracking of all combinations here? Or is it possible to implement this task in another way?
MaskedTextBox requires a fixed number of characters with some "mask". But the Salary is different. Can be **,**, ******,* or *** and etc.
UPDATE
Prevent entering more than two numbers after the decimal point
if (number < ' ')
{
return;
}
if (number >= '0' && number <= '9')
{
if (this.Text.Contains(',')
&& this.SelectionLength == 0
&& this.SelectionStart > this.Text.IndexOf(',')
&& this.Text.Length - this.Text.IndexOf(',') > 2)
{
e.Handled = true;
}
return;
}

Please, don't use magic numbers like 47, let's work with characters. We should allow these characters:
'0'..'9' range (numbers)
control characters (which are below space ' ') for tab, backspace etc.
',' (comma) as a decimal separator
All the other characters should be banned.
Code:
private void TbSalary_KeyPress(object sender, KeyPressEventArgs e)
{
char number = e.KeyChar;
TextBox box = sender as TextBox;
if (number >= '0' && number <= '9' || number < ' ')
return; // numbers as well as backspaces, tabs: business as usual
else if (number == ',') {
// We don't want to allow several commas, right?
int p = box.Text.IndexOf(',');
// So if we have a comma already...
if (p >= 0) {
// ... we don't add another one
e.Handled = true;
// but place caret after the comma position
box.SelectionStart = p + 1;
box.SelectionLength = 0;
}
else if (box.SelectionStart == 0) {
// if we don't have comma and we try to add comma at the 1st position
e.Handled = true;
// let's add it as "0,"
box.Text = "0," + box.Text.Substring(box.SelectionLength);
box.SelectionStart = 2;
}
}
else
e.Handled = true; // all the other characters (like '+', 'p') are banned
}
Please, note, that there is possibility to Paste incorrect value (say, "bla-bla-bla") into TbSalary TextBox; to prevent it you can use TextChanged event:
private void TbSalary_TextChanged(object sender, EventArgs e) {
TextBox box = sender as TextBox;
StringBuilder sb = new StringBuilder();
bool hasComma = false;
foreach (var c in box.Text)
if (c >= '0' && c <= '9')
sb.Append(c);
else if (c == ',' && !hasComma) {
hasComma = true;
if (sb.Length <= 0) // we don't start from comma
sb.Append('0');
sb.Append(c);
}
string text = sb.ToString();
if (!text.Equals(box.Text))
box.Text = text;
}

Related

Regex mask with replace for digits and only one hyphen C#

I saw a similar topic (this) but could not reach the ideal solution.
What I need:
A mask that works on the keypress event of aTextBox replacing non-numeric and excessive hyphens with "".
Allowing:
What is my difficulty?
Check for the entry of only one hyphen in the same expression.
I got into the solution using substring and it only worked in KeyUP, but I wanted to get through using an expression and keypress event.
What I've already tried:
using System.Text.RegularExpressions;
//trying to denie non-digit and hyphen.
//In conjunction with replace I remove everything that is not hyphen and digit
private static Regex MyMask = new Regex(#"[^\d-]");
private void inputSequential_KeyUp (object sender, KeyEventArgs e)
{
if (! String.IsNullOrEmpty (inputSequential.Text)
{
inputSequential.Text = MyMask.Replace (inputSequential.Text, "");
// MatchCollection matches = Regex.Matches (inputSequential.Text, "[\\ -]");
//
// if (matches.Count> 1)
// {
// for (int i = 1; i <= matches.Count - 1; i ++)
// {
// inputSequential.Text = inputSequential.Text.Substring (0, matches [i] .Index-1) + inputSequential.Text.Substring (matches [i] .Index, inputSequential.Text.Length);
// inputSequential.Text = inputSequential.Text.Replace (inputSequential.Text [matches [i] .Index] .ToString (), "");
//}
//}
}
}
Expected:
If you know better ways to do this please let me know.
Thanks for listening.
You can use a LINQ expression to get only the numbers and one hyphen:
string input = "12-3-47--Unwanted Text";
int hyphenCount = 0;
string output = new string(input.Where(ch => Char.IsNumber(ch) || (ch == '-' && hyphenCount++ < 1)).ToArray());
You seem at lost:
that expression: (:? ) - is not a nonmatched group. The correct variant is : (?: )
digitsOnly - it will be \d?
You should not escape -
If you are looking for a -, simply write it down.
For regex - Better write down in words, what are you looking for. For excluding or for taking in, does not matter, but SAY IN ENGLISH, what do you need.
Please, write down examples that should be accepted and these ones that should NOT be accepted.
For getting only numbers, possibly with - before, use:
-?\d+
tests
I searched here for some alternatives, with Regex or MaskedTextBox (This did not help me much because by default it is not supported in toolStrip where my textBox was).
At the end of the day the best solution I found was dealing with the input of values ​​to each char:
private void inputSequencial_KeyPress(object sender, KeyPressEventArgs e)
{
//Allow only digits(char 48 à 57), hyphen(char 45), backspace(char 8) and delete(char 127)
if ((e.KeyChar >= 48 && e.KeyChar <= 57) || e.KeyChar == 45 || e.KeyChar == 8 || e.KeyChar == 127)
{
switch (e.KeyChar)
{
case (char)45:
int count = inputSequencial.Text.Split('-').Length - 1;
//If the first char is a hyphen or
//a hyphen already exists I reject the entry
if (inputSequencial.Text.Length == 0 || count > 0)
{
e.Handled = true;
}
break;
}
}
else
{
e.Handled = true; //Reject other entries
}
}
private void inputSequencial_KeyUp(object sender, KeyEventArgs e)
{
//if last char is a hyphen i replace it.
if (inputSequencial.Text.Length > 1)
{
string lastChar = inputSequencial.Text.Substring(inputSequencial.Text.Length - 1, 1);
if (lastChar == "-")
{
inputSequencial.Text.Replace("-", "");
}
}
}
You can use this for nondigit [^\d]:
var st = "1kljkj--2323'sdfkjasdf2";
var result = Regex.Replace(st, #"^(\d).*?(-)[^\d]*(\d+)[^\d]*", #"$1$2$3");
1-23232

C# Masked TextBox with 0 or decimals

Users have a textbox where they have to either enter a 0 or a value from 0.0001 to 0.9999.
What regex can I use here? I have looked at other examples but don't see anything like this one.
I'd say this is quite an effective solution. It allows for any strings entered that is either just a '0' or strings with '0.' followed by up to 4 of any digit.
Regex myRegex = new Regex("^(?:(?:0)|(?:0.[0-9]{1,4}))$");
Console.WriteLine("Regex: " + myRegex + "\n\nEnter test input.");
while (true)
{
string input = Console.ReadLine();
if (myRegex.IsMatch(input))
{
Console.WriteLine(input + " is a match.");
}
else
{
Console.WriteLine(input + " isn't a match.");
}
}
Here's a list of tests...
Try this one:
/(0)+(.)+([0-9])/g
Also see thing link that might helps you build you won expreession.
http://regexr.com/
Try this, it will do the work but I was not tested for all cases.
Regex _regex = new Regex("^[0]+(.[0-9]{1,4})?$");
if (input == "0" || _regex.IsMatch(input))
{
//Match
}
else
{
//Does not match
}
Note: input is a string, in your case Textbox.Text!
This is ready to use KeyPress event handler of TextBox control. It will prevent any input, except numeric between 0.0001 and 0.9999:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
//Only one dot is possible
if ((sender as TextBox).Text.Contains('.') && (e.KeyChar == '.')) e.Handled = true;
//Only numeric keys are acceptable
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && (e.KeyChar != '.')) e.Handled = true;
//Only one zero in front is acceptable, next has to be dot
if (((sender as TextBox).Text == "0") && (e.KeyChar == '0')) e.Handled = true;
double value = 0;
string inputValue = (sender as TextBox).Text + e.KeyChar;
if ((sender as TextBox).Text.Length > 0)
{
//Just in case parse input text into double
if (double.TryParse(inputValue, out value))
{
//Check if value is between 0.0001 and 0.9999
if (value > 0.9999) e.Handled = true;
if (((sender as TextBox).Text.Length > 4) && (value < 0.0001)) e.Handled = true;
}
}
else if (e.KeyChar != '0')
{
e.Handled = true;
}
}

How to limit the length of each line in a multiline textbox on PowerPoint TaskPane using C#?

I have created a task-pane in PowerPoint VSTO add-in which I have developed on .Net 4.0.
On the task-pane, I have a text box where the user has to enter only numeric data.
The requirement is as below:
The user can enter more than one numeric data by typing one data on each line.
Each data can contain up to 8 characters, including: numbers, decimals and commas. If a line exceeds 8 characters, it should be truncated to 8 characters.
Below is the code that I am using:
public void splitString(string[] strText)
{
string[] arr = txtEntryField.Lines;
for (int n = 0; n < arr.Length; n++)
{
if (arr[n].Length > 8)
{
arr[n] = arr[n].Substring(0, 8);
}
}
txtEntryField.Lines = arr;
if (txtEntryField.Lines.Length > 0)
{
txtEntryField.SelectionStart = txtEntryField.Text.Length;
}
}
I am calling this method on txtEntryField_TextChanged event. While I am almost there, I think the operation and user experience is not so smooth.
Updated the code so that user is not able to enter characters in the textbox. This is done by the following code:
void txtEntryField1_KeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char)8;
var regex = new Regex(#"[^.,0-9\s]");
if (regex.IsMatch(e.KeyChar.ToString()) && e.KeyChar != Delete && e.KeyChar != (char)Keys.Enter && e.KeyChar != (char)Keys.Back)
{
e.Handled = true;
}
}
Can any one help me with a better solution?
Any help is most welcome.
Thanks.
This worked for me:
public void splitString(string[] strText)
{
string[] arr = txtEntryField.Lines;
for (int n = 0; n < arr.Length; n++)
{
if (arr[n].Length > 8)
{
arr[n] = arr[n].Substring(0, 8);
}
}
txtEntryField.Lines = arr;
if (txtEntryField.Lines.Length > 0)
{
txtEntryField.SelectionStart = txtEntryField.Text.Length;
}
}
Also the below code allows the user only to enter the desired characters:
void txtEntryField1_KeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char)8;
var regex = new Regex(#"[^.,0-9\s]");
if (regex.IsMatch(e.KeyChar.ToString()) && e.KeyChar != Delete && e.KeyChar != (char)Keys.Enter && e.KeyChar != (char)Keys.Back)
{
e.Handled = true;
}
}

How restrict textbox in C# to only receive numbers and (dot "." or comma ","), after "." or "," only allow 2 number characters

i am trying develop a code to restrict TextBox using C# to only allow numbers entry + comma(",") or dot(".") + only 2 numbers after dot or comma
So this way see possible numbers that can entry:
3213,04 = OK
3211,664 = Not
32.31 = OK
32.3214 = Not
334,,00 = Not
3247,.00 = Not
214.,00 = Not
32.. = Not
8465,0 = Ok
654.0 = Ok
Understood My goal ?
I developed code bellow
private void txtValormetrocubico_KeyPress(object sender, KeyPressEventArgs e)
{
if (txtValormetrocubico.TextLength >= 0 && (e.KeyChar == (char)Keys.OemPeriod || e.KeyChar == (char)Keys.Oemcomma))
{
//tests
}
else
{
if (!char.IsControl(e.KeyChar)
&& !char.IsDigit(e.KeyChar)
&& e.KeyChar != '.' && e.KeyChar != ',')
{
e.Handled = true;
}
// only allow one decimal point
if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1)
{
e.Handled = true;
}
if (e.KeyChar == ',' && (sender as TextBox).Text.IndexOf(',') > -1)
{
e.Handled = true;
}
}
}
This is auxiliary function I have written
private bool alreadyExist(string _text , ref char KeyChar)
{
if (_text.IndexOf('.')>-1)
{
KeyChar = '.';
return true;
}
if (_text.IndexOf(',') > -1)
{
KeyChar = ',';
return true;
}
return false;
}
This your key press event handler
private void txtValormetrocubico_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar)
&& !char.IsDigit(e.KeyChar)
&& e.KeyChar != '.' && e.KeyChar != ',')
{
e.Handled = true;
}
//check if '.' , ',' pressed
char sepratorChar='s';
if (e.KeyChar == '.' || e.KeyChar == ',')
{
// check if it's in the beginning of text not accept
if (txtValormetrocubico.Text.Length == 0) e.Handled = true;
// check if it's in the beginning of text not accept
if (txtValormetrocubico.SelectionStart== 0 ) e.Handled = true;
// check if there is already exist a '.' , ','
if (alreadyExist(txtValormetrocubico.Text , ref sepratorChar)) e.Handled = true;
//check if '.' or ',' is in middle of a number and after it is not a number greater than 99
if (txtValormetrocubico.SelectionStart != txtValormetrocubico.Text.Length && e.Handled ==false)
{
// '.' or ',' is in the middle
string AfterDotString = txtValormetrocubico.Text.Substring(txtValormetrocubico.SelectionStart);
if (AfterDotString.Length> 2)
{
e.Handled = true;
}
}
}
//check if a number pressed
if (Char.IsDigit(e.KeyChar))
{
//check if a coma or dot exist
if (alreadyExist(txtValormetrocubico.Text ,ref sepratorChar))
{
int sepratorPosition = txtValormetrocubico.Text.IndexOf(sepratorChar);
string afterSepratorString = txtValormetrocubico.Text.Substring(sepratorPosition + 1 );
if (txtValormetrocubico.SelectionStart > sepratorPosition && afterSepratorString.Length >1)
{
e.Handled = true;
}
}
}
}
I think you need something like Masked Textbox control here you have some references
http://msdn.microsoft.com/en-us/library/kkx4h3az.aspx
http://www.c-sharpcorner.com/uploadfile/mahesh/maskedtextbox-in-C-Sharp/
Another way to do what you want is to use regular expressions
Well you can create a general function and call it on keypress event this code is a general instance.
validate_textBox is a general function
private void validate_textBox(TextBox _text, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar)
&& !char.IsDigit(e.KeyChar)
&& e.KeyChar != '.' && e.KeyChar != ',')
{
e.Handled = true;
}
if (!char.IsControl(e.KeyChar)
&& !char.IsDigit(e.KeyChar)
&& e.KeyChar != '.' && e.KeyChar != ',')
{
e.Handled = true;
}
//check if '.' , ',' pressed
char sepratorChar = 's';
if (e.KeyChar == '.' || e.KeyChar == ',')
{
// check if it's in the beginning of text not accept
if (_text.Text.Length == 0) e.Handled = true;
// check if it's in the beginning of text not accept
if (_text.SelectionStart == 0) e.Handled = true;
// check if there is already exist a '.' , ','
if (alreadyExist(_text.Text, ref sepratorChar)) e.Handled = true;
//check if '.' or ',' is in middle of a number and after it is not a number greater than 99
if (_text.SelectionStart != _text.Text.Length && e.Handled == false)
{
// '.' or ',' is in the middle
string AfterDotString = _text.Text.Substring(_text.SelectionStart);
if (AfterDotString.Length > 2)
{
e.Handled = true;
}
}
}
//check if a number pressed
if (Char.IsDigit(e.KeyChar))
{
//check if a coma or dot exist
if (alreadyExist(_text.Text, ref sepratorChar))
{
int sepratorPosition = _text.Text.IndexOf(sepratorChar);
string afterSepratorString = _text.Text.Substring(sepratorPosition + 1);
if (_text.SelectionStart > sepratorPosition && afterSepratorString.Length > 1)
{
e.Handled = true;
}
}
}
}
Then you can call function like this code for each textbox you have in the form
private void txtValormetrocubico_KeyPress(object sender, KeyPressEventArgs e)
{
validate_textBox(sender as TextBox, e);
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
validate_textBox(sender as TextBox, e);
}
I don't know who is looking for this in 2021 but here is one solution overriding the ontextchange event! Cheers
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
String text = "";
Char[] chars = this.Text.ToString().ToCharArray();
int total_dots = 0;
int dot_pos = 0;
int char_pos = 0;
foreach (Char c in chars )
{
char_pos++;
if (Char.IsDigit(c))
{
if(dot_pos > 0) { //dot already exists
if (char_pos <= dot_pos + 2) //only accept two numbers after dot (3.99)
{
text += c.ToString();
}
}
else
{
text += c.ToString();
}
}
if(c == '.' || c == ',')
{
total_dots++;
if (char_pos > 1 && total_dots <=1) //only accept one dot and if the dot is not in first position
{
text += c.ToString();
dot_pos = char_pos;
}
}
}
this.Text = text;
this.SelectionStart = this.Text.Length;
}

Fire event on word wrap, multiline TextBox (Winforms)

So, I have written a method for limiting the number of lines allowed to write in a multiline textbox (since this is not a property provided by Microsoft). The method works in all cases, except when a wordwrap event occurs (when typing a single char, or when pasting text from clipboard). The code I hace right now:
protected void limitLineNumbers(object sender, KeyPressEventArgs e, UInt16 numberOfLines)
{
int[] specialChars = { 1, 3, 8, 22, 24, 26 }; // ctrl+a, ctrl+c, backspace, ctrl+v, ctrl+x, ctrl+z
bool found = false;
string lastPressedChar = "";
TextBox temp = (TextBox)sender;
foreach (int i in specialChars)
{
if (i == (int)e.KeyChar)
found = true;
}
if (!found)
lastPressedChar = e.KeyChar.ToString(); // Only add if there is a "real" char
int currentLine = temp.GetLineFromCharIndex(temp.SelectionStart) + 1;
int totalNumberOfLines = temp.GetLineFromCharIndex(temp.TextLength) + 1;
if ((int)e.KeyChar == 1)
temp.SelectAll();
// Paste text from clipboard (ctrl+v)
else if ((int)e.KeyChar == 22)
{
string clipboardData = Clipboard.GetText();
int lineCountCopiedText = 0;
foreach (char c in clipboardData)
{
if (c.Equals("\n"))
++lineCountCopiedText;
}
if ((currentLine > numberOfLines || (totalNumberOfLines + lineCountCopiedText) > numberOfLines))
e.Handled = true;
}
// Carrige return (enter)
else if ((int)e.KeyChar == 13)
{
if ((currentLine + 1) > numberOfLines || (totalNumberOfLines + 1) > numberOfLines)
e.Handled = true;
}
// Disallow
else if ((currentLine > numberOfLines) || (totalNumberOfLines > numberOfLines))
e.Handled = true;
}
So, do you guys have some ideas how I can make this method more complete? The best solution would be to catch the wordwrap event, but as far as I can understand, this can't be done? The other solution would be to delete the line(s) of text, if it exceeds the maximum allowed.
Or is it possible a better solution than the one I came up with? Appreciate your input.

Categories