Can I determine if a KeyEventArg is an letter or number? - c#

Is there a way to determine if a key is letter/number (A-Z,0-9) in the KeyEventArgs? Or do I have to make it myself? I found a way with e.KeyCode, is that accurate?
if(((e.KeyCode >= Keys.A && e.KeyCode <= Keys.Z )
|| (e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9 )
|| (e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9))

You can use the char.IsLetterOrDigit() method on the KeyCode of the event args:
bool isLetterOrDigit = char.IsLetterOrDigit((char) keyEventArgs.KeyCode);

Char.IsNumber() and Char.IsLetter()

In WPF? Use PreviewTextInput or TextInput events instead of KeyDown

Char.IsLetter() accepts some of OEM key codes that was treated as alphabetical characters.
My case was when I typed a keyboard (tilde) then this Keycode was returned OEM3.
I inspected the value (tilde) and it says
"192 'A'"
But actual typing 'A' was
"65 'A'"
As a result, both passed Char.IsLetter() as True.
To avoid this, I put below code.
private bool IsAlphabetOrDigit(System.Windows.Forms.KeyEventArgs e)
{
var keyCode = (char)e.KeyCode;
if ( false == char.IsNumber( keyCode ) && false == ((keyCode >= 'a' && keyCode <= 'z') || (keyCode >= 'A' && keyCode <= 'Z')))
{
return false;
}
return true;
}

Related

How to accept just certain characters into a textbox?

How do I limit textbox from accepting letter A,B,C,D only? I've tried this code, but it still accepts letters aside from letters A,B,C,D.
e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);
I agree with the comment that if all you want is a single character that actually using a combo box may be more appropriate, but if you're planning on allowing the user to enter a series of the limited characters then it may be worth having a look at an article that I wrote a few years ago about how to restrict the characters that are allowed in the text box, which is available at "Restrict characters entered into textbox".
Further to DanDan78's comment below the important code is;
Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
Dim allowedChars As String = "0123456789"
If allowedChars.IndexOf(e.KeyChar) = -1 Then
' Invalid Character
e.Handled = True
End If
End Sub
On the KeyPress event of your TextBox, you can just use this simple code to achieve your aim:
if (e.KeyChar < 'A' || e.KeyChar > 'D')
e.Handled = true;
If you wish to accept lower and upper case A-D:
if ((e.KeyChar < 'A' || e.KeyChar > 'D') && (e.KeyChar <'a' || e.KeyChar > 'd'))
e.Handled = true;
If you also wish to allow 'special' characters like backspace, delete, etc., you need to also allow characters below ASCII code 32:
if ((e.KeyChar < 'A' || e.KeyChar > 'D') && (e.KeyChar <'a' || e.KeyChar > 'd') && e.KeyChar > 32)
e.Handled = true;
Following a further user comment, in order to allow A-D, a-d and backspace only, the following should suffice:
if ((e.KeyChar < 'A' || e.KeyChar > 'D') && (e.KeyChar <'a' || e.KeyChar > 'd') && e.KeyChar != 8)
e.Handled = true;
Attach a KeyPressEventHandler to the text box:
textBox.KeyPress += new KeyPressEventHandler(keyPressed);
Then create an event to handle these letters:
private void keyPressed(Object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 'A' || e.KeyChar == 'B' || e.KeyChar == 'C' || e.KeyChar == 'D')
{
e.Handled = true;
}
}
This will stop the text box accepting these letters

WPF Key is digit or number

I have previewKeyDown method in my window, and I'd like to know that pressed key is only A-Z letter or 1-0 number (without anyF1..12, enter, ctrl, alt etc - just letter or number).
I've tried Char.IsLetter, but i need to give the char, so e.key.ToString()[0] doesn't work, because it is almost everytime a letter.
Something like this will do:
if ((e.Key >= Key.A && e.Key <= Key.Z) || (e.Key >= Key.D0 && e.Key <= Key.D9) || (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9))
Of course you will also have to check that no modifier keys like CTRL are pressed according to your requirements.
e.Key is giving you a member of the enum System.Windows.Input.Key
You should be able to do the following to determine whether it is a letter or a number:
var isNumber = e.Key >= Key.D0 && e.Key <= Key.D9;
var isLetter = e.Key >= Key.A && e.Key <= Key.Z;
In your specific case the answer provided by Jon and Jeffery is probably best, however if you need to test your string for some other letter/number logic then you can use the KeyConverter class to convert a System.Windows.Input.Key to a string
var strKey = new KeyConverter().ConvertToString(e.Key);
You'll still need to check to see if any modifier keys are being held down (Shift, Ctrl, and Alt), and it should also be noted that this only works for Letters and Numbers. Special characters (such as commas, quotes, etc) will get displayed the same as e.Key.ToString()
try this, it works.
private void txbNumber_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key >= Key.D0 && e.Key <= Key.D9) ; // it`s number
else if (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9) ; // it`s number
else if (e.Key == Key.Escape || e.Key == Key.Tab || e.Key == Key.CapsLock || e.Key == Key.LeftShift || e.Key == Key.LeftCtrl ||
e.Key == Key.LWin || e.Key == Key.LeftAlt || e.Key == Key.RightAlt || e.Key == Key.RightCtrl || e.Key == Key.RightShift ||
e.Key == Key.Left || e.Key == Key.Up || e.Key == Key.Down || e.Key == Key.Right || e.Key == Key.Return || e.Key == Key.Delete ||
e.Key == Key.System) ; // it`s a system key (add other key here if you want to allow)
else
e.Handled = true; // the key will sappressed
}
Add a reference to Microsoft.VisualBasic and use the VB IsNumeric function, combined with char.IsLetter().
bit of a cludge but it works :)
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
Regex R = new Regex("^([A-Z]|[0-9]){1}$");
var strKey = new KeyConverter().ConvertToString(e.Key);
if(strKey.Length > 1 )
{
strKey = strKey.Replace("NumPad", "").Replace("D", "");
}
if (strKey.Length == 1)
{
if (!R.IsMatch(strKey))
{
e.Handled = true;
}
}
else
{
e.Handled = true;
}
}
Can you put some code to show what you intend? Shouldn't this work for you
if(e.key.ToString().Length==1)
`Char.IsLetter(e.key.ToString()[0])`
else
//

Setting an attribute to only allow doubles in a textbox

I remember using some attribute on the getter/setter that would limit the input to a certain datatype, length etc. IE [Attribute something something].
Any ideas?
Thanks
Did you mean the ValidateInput attribute available in System.Web.Mvc?
Also, you could probably use a MaskedTextBox if you're doing WinForms.
One way to do it (if you want to keep using a standard text box) would be to make an event for the text changed event of the text box, and in that, read the text to make sure that it contains only numbers (and an optional period in the case of a double)
Winforms? Have you considered using masked Textbox control?
http://msdn.microsoft.com/en-us/library/system.windows.forms.maskedtextbox.aspx
Winforms? Why not use a NumericUpDown?
http://msdn.microsoft.com/en-us/library/57dy4d56.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.numericupdown.aspx
If you need scientific notation you can do :
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
TextBox tBox = (TextBox)sender;
if (!((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9)
|| (e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9)
|| (e.KeyCode == Keys.Decimal && !(tBox.Text.Contains('.'))
&& !(tBox.Text.Length == 0)
&& !((tBox.Text.Length == 1)
&& (tBox.Text.Contains('-') || tBox.Text.Contains('+'))))
|| (e.KeyCode == Keys.OemPeriod && !(tBox.Text.Contains('.'))
&& !(tBox.Text.Length == 0)
&& !((tBox.Text.Length == 1)
&& (tBox.Text.Contains('-') || tBox.Text.Contains('+'))))
|| (e.KeyCode == Keys.Subtract && ((tBox.Text.Length == 0) ||
tBox.Text.EndsWith("e") || tBox.Text.EndsWith("E")))
|| (e.KeyCode == Keys.OemMinus && ((tBox.Text.Length == 0) ||
tBox.Text.EndsWith("e") || tBox.Text.EndsWith("E")))
|| (e.KeyCode == Keys.Add && ((tBox.Text.Length == 0) ||
tBox.Text.EndsWith("e") || tBox.Text.EndsWith("E")))
|| (e.KeyCode == Keys.Oemplus && ((tBox.Text.Length == 0) ||
tBox.Text.EndsWith("e") || tBox.Text.EndsWith("E")))
|| e.KeyCode == Keys.Delete
|| e.KeyCode == Keys.Back
|| e.KeyCode == Keys.Left
|| e.KeyCode == Keys.Right
|| (e.KeyCode == Keys.E) && !(tBox.Text.Contains('e')) &&
(tBox.Text.Contains('.') && !tBox.Text.EndsWith("."))))
{
e.SuppressKeyPress = true;
}
}
This will deny input of any pattern which is not consistent with a numeric value. Minus signs are only allowed at the beginning of the string (to indicate a negative number) and after an e or E to indicate a negative exponent. Plus signs follow the same rule as minus. Only one decimal point is allowed and it must follow at least one number. Only one e or E is allowed and it must follow a decimal point and at least one number after the decimal point.
You could also allow things like the Help, Tab, etc, keys if it would interfere with other aspects of your program function.
Note that this does not prevent incomplete numbers (ie: 1.37E- or -13. from being entered so you would probably want to check the string in any case. This at least denies any immediately invalid entries.
You might do something like (in the same handler, before the other logic):
if (e.KeyCode == Keys.Enter)
{
textBox1_Validating(sender, new CancelEventArgs());
return;
}
The above only gives the enter key the normal 'feel' for input (force validation). Leaving the textbox (going out of focus) will also trigger validation where you might do something like :
private void textBox1_Validating(object sender, CancelEventArgs e)
{
TextBox tBox = (TextBox)sender;
double tstDbl;
if (!double.TryParse(tBox.Text, out tstDbl))
{
//handle bad input
}
else
{
//double value OK
doSomething(tstDbl);
}
}

More efficient way of screening KeyCodes on KeyDown Event

I'm trying to fire an event perform some work when the user tries to enter only useful data into a form-field using the KeyDown event. But, I keep getting false alarms because the KeyDown event works for just any key!
I'm trying not to make the event fire for buttons such as "Alt, Control, Shift, Esc, the F-keys, etc." What's the best way of doing this?
What I have so far is this:
private void formControl_KeyModified(object sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Shift && e.KeyCode != Keys.CapsLock && e.KeyCode != Keys.Tab && e.KeyCode != Keys.Escape &&
e.KeyCode != Keys.Insert && e.KeyCode != Keys.Home && e.KeyCode != Keys.End && e.KeyCode != Keys.PageUp &&
e.KeyCode != Keys.PageDown && e.KeyCode != Keys.Up && e.KeyCode != Keys.Down && e.KeyCode != Keys.Left &&
e.KeyCode != Keys.Right && e.KeyCode != Keys.Control && e.KeyCode != Keys.Alt && e.KeyCode != Keys.NumLock &&
e.KeyCode != Keys.Insert && e.KeyCode != Keys.None && e.KeyCode != Keys.PrintScreen && e.KeyCode != Keys.Help &&
e.KeyCode != Keys.ControlKey && e.KeyCode != Keys.ShiftKey && e.KeyCode != Keys.Sleep && e.KeyCode != Keys.LWin &&
e.KeyCode != Keys.RWin && e.KeyCode != Keys.RMenu && e.KeyCode != Keys.LMenu && e.KeyCode != Keys.LShiftKey &&
e.KeyCode != Keys.RShiftKey && e.KeyCode != Keys.Pause && e.KeyCode != Keys.F1 && e.KeyCode != Keys.F2 &&
e.KeyCode != Keys.F3 && e.KeyCode != Keys.F4 && e.KeyCode != Keys.F5 && e.KeyCode != Keys.F6 && e.KeyCode != Keys.F7 &&
e.KeyCode != Keys.F8 && e.KeyCode != Keys.F9 && e.KeyCode != Keys.F10 && e.KeyCode != Keys.F11 && e.KeyCode != Keys.F12 &&
e.KeyCode != Keys.L)
{
// Do some work...
}
}
However, that doesn't quite seem like the best way to handle this to me. Again, I'm just trying to get keys for the characters that could be entered into a textbox (such as 213135udf!##%#!###%15nfaosdf~!#}{:?>, and so on)! Any help at all will be appreciated, thanks!
Sincerely,
Isaac D.
(Edited for clarity and quality)
You could throw all values into a HashSet<T> and check if the KeyCode is in the set.
var invalidKeys = new HashSet<Keys> { Keys.Shift, Keys.CapsLock, Keys.Tab, ... Keys.L };
if (!invalidKeys.Contains(e.KeyCode))
{
// Do some work...
}
Or alternatively, since you're checking for equality, you could just throw all that into a switch statement.
switch (e.KeyCode)
{
case Keys.Shift:
case Keys.CapsLock:
case Keys.Tab:
// ...
case Keys.L:
break;
default:
// Do some work...
break;
}
you can for example (there are many good attempts) check this page for help on the Char class where you can use methods like IsLetterOrDigit or other functions. Now I could not recognise if you are using Windows Forms? If so, use a simple cast like (char)e.KeyCode to get the char.
Example:
private void formControl_KeyModified(object sender, KeyEventArgs e)
{
char c = (char)e.KeyCode;
if (Char.IsLetterOrDigit(c)) {
// useful
}
// might add more checks
// else if (Char.IsPunctuation(c)) ...
}
You can handle the KeyPress event of the form. The mentioned event take a KeyPressEventArgs as its arguments parameter.
Use the Char.IsLetterOrDigit function to check the value of the KeyPressEventArgs.KeyChar property.
private void form_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (char.IsLetterOrDigit(e.KeyChar)) {}
else { e.Handled = false; }
}
EDIT:
You can also try to make a list of your accepted Char values, then check if the preseed character is included in it:
private void form_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
List<Char> charList = new List<Char>;
charList.AddRange(new Char[] { 'a', 'b' ... });
if (charList.Contains(e.KeyChar)) {}
else { e.Handled = false; }
}
You may need to consider combining both ways or even more to fulfill your requirements.
If you are concerned with the execution time of the if statement, create a SortedList of the Key values and check if the SortedList contains your key.
A possibly better solution is to use the Forms TextBox "TextChanged" event rather than using the KeyDown event.
Like #Daniel states in his comment, perhaps white-listing the valid keys is preferable than black-listing all those that are of no interest to you. So if, let's say, you are interested only in letter keys and numbers, you could do it just like it is described in the msdn Keys example
if(e.KeyCode > Keys.NumPad0 && e.KeyCode < Keys.NumPad9 ||
e.KeyCode > Keys.D0 && e.KeyCode < Keys.D9 ||
e.KeyCode > Keys.A && e.KeyCode < Keys.Z) {
//do useful stuff here
}

C# Hex Mask for maskedtextbox input

I'm trying to set a hex mask for a textbox. So that only valid hex numbers can be entered. (And ',' and 'ENTER')
It almost works. So far it will only allow small letters from a-f and numbers 0-9, but I can still enter capital letters GHIJKLM. (At first, when program is started it seems to accept one char ex k, but after it has excepted k once it wont be shown after that, until next time you start the program. That's weird.)
Here is a part of code:
private void EnterKey(Object sender, System.Windows.Forms.KeyPressEventArgs e)
{
// if keychar == 13 is the same as check for if <ENTER> was pressed
if (e.KeyChar == (char)13)
{
// is <ENTER> pressed, send button_click
button1_Click(sender, e);
}
{
// this will only allow valid hex values [0-9][a-f][A-F] to be entered. See ASCII table
char c = e.KeyChar;
if (c != '\b' && !((c <= 0x66 && c >= 61) || (c <= 0x46 && c >= 0x41) || (c >= 0x30 && c <= 0x39) || (c == 0x2c)))
{
e.Handled = true;
}
}
}
This is how I bind the event:
private void textBox1_TextChanged(object sender, EventArgs e)
{
this.textBox1.KeyPress += new KeyPressEventHandler(textBox1_KeyDown);
}
Could anyone of you wise guys, see what I'm doing wrong?
It's my first small program, so go easy on me :o)
This:
c <= 0x66 && c >= 61
Should be:
c <= 0x66 && c >= 0x61 //hex literal
Note that you're wasting valuable time by looking up hex codes, you can easily compare characters:
if ((c >= 'a') && (c <= 'f'))
As for the first character: you shouldn't bind the KeyPress at the TextChanged event - it is too late! Here's the sequence of events:
Form Loads
...
User click on a key.
TextChanged triggered, changing the text and binding the event.
User click on a key.
KeyPress triggered.
What you want to do is to bind the event right from the start. The best place is the Form_Load event.
You can also use the Properties window to bind the event at design time
If you had not used magic numbers, you would never have run into this problem. Rewrite your if like this:
if (!(c == '\b' || ('0' <= c && c <= '9') || ('A' <= c && c <= 'F') // et cetera
Use a regular expression:
using System.Text.RegularExpressions;
...
if (!(Regex.IsMatch(e.KeyChar.ToString(), "^[0-9a-fA-F]+$"))
e.Handled = true;
What type of program is this an ASP.NET website or some type of winforms/wpf thick client? The reason I ask is that you may be testing on stale code. Otherwise on change can be to just flip the checking logic to be more aligned with what you want. Ensuring that the entered character is one element in the allowed set. A refactoring is below.
e.Handled = (c >= 0x61 && c <=0x66) || (c >=0x41 && c<= 0x46) || (c >= 0x30 && c <= 0x39);
As an alternative approach if you just want to validate the whole textbox at one time instead of after each key press you can just parse the value to see if it is a number. The following code fragment will generate parse the value 11486525 from AF453d. If the number is not a valid hex value then the result of isHex will be false;
int i;
string s = "AF453d";
bool isHex;
isHex = int.TryParse(s, System.Globalization.NumberStyles.AllowHexSpecifier, null, out i);
Console.WriteLine(isHex);
Console.WriteLine(i);
Why complicate it?
private void EnterKey(Object sender, System.Windows.Forms.KeyPressEventArgs e)
{
char c = e.KeyChar;
e.Handled = !System.Uri.IsHexDigit(e.KeyChar) && c != 0x2C;
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e) {
/* less than 0 or greater than 9, and
* less than a or greater than f, and
* less than A or greater than F, and
* not backspace, and
* not delete or decimal (which is the same key as delete). */
if (
((e.KeyChar < 48) || (e.KeyChar > 57)) &&
((e.KeyChar < 65) || (e.KeyChar > 70)) &&
((e.KeyChar < 97) || (e.KeyChar > 102)) &&
(e.KeyChar != (char)Keys.Back) &&
((e.KeyChar != (char)Keys.Delete) || (e.KeyChar == '.'))
) e.Handled = true;
}
Based on the answer by Kobi for WPF
private void EnterKey(Object sender, KeyEventArgs e)
{
Key c = e.Key;
if (!((c >= Key.A) && (c <= Key.F)))
{
if (!((c >= Key.D0) && (c <= Key.D9)))
{
if (!((c >= Key.NumPad0) && (c <= Key.NumPad9)))
{
e.Handled = true;
LogText("Handled");
}
}
}
}
Captures letters, numbers and keypad numbers.

Categories

Resources