0
votes

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)

5
Can you write your if() for 'useful data'?Daniel Mošmondor
Aren't you going about this a bit backwards? Why not just handle TextChanged and if something the user has pressed has resulted in a change in the text in the textbox, then what they pressed was "useful".Shibumi
@Shibumi - Not at all. Control.TextChanged won't work in my case because I'm using databinding with Binding.Format and Binding.Parse. Whenever the form loads, TextChanged is triggered because the controls pull data from the database and fill the control's value and then are evaluated, giving a faux pas. Also, since the form controls are within a TabControl, whenever the tabControl's SelectedIndexChanged is triggered (when changing tabs), TextControl is triggered again. So, the TextChanged event can't have that use in this case because it would detect everything as modified.Isaac
@Daniel Actually, what I did is screen for both useful data and unuseful data. It only worked when screening for both. So, I validated for the normal a-z, A-Z, 0-9, symbols, and characters, but I also excluded the F keys, many of the function keys, the Alt modifiers, and Ctrl + V modifiers from the result. That ended up being the most functional and secure.Isaac
That seems to be a case where you would specifically bind to that event when you knew it was relevant. Only bind to the event when databinding is complete. Unbind before tab changes and re-bind afterward. All of that, to me, is still preferable to all of that key code checking.Shibumi

5 Answers

1
votes

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

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)) ...
}
0
votes

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.

0
votes

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.

0
votes

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
}