views:

2522

answers:

10

This seems like something that should be easy, but I am having a tough time figuring out what needs to happen here.

In the "KeyDown" eventhandler, if the "e.KeyValue" is a number, I want to treat it as a number and store it as an int. So, if I hit "8" on the number pad, I don't want "Numpad8" I want the int value 8 that I can add or subtract or whatever.

So, how do I convert from the KeyValue to an int?

+2  A: 

Depending on how many keys you are keeping track of, the simplest method would be for you to create a select case (or switch statement in C# I guess?) that would check the value of your keydown and depending upon that value assign a value to an integer that is appropriate.

TheTXI
Ugh... I can do that, but it feels so dirty. I'd have to check for both the numpad values and the other numbers above the keyboard. Seems like a lot of checking for something that just feels like should be common.
Andy Stampor
While it may seem that way to you, I'd be quite surprised if this was common at all. The closest you might come would be someone parsing a numeric value from a string that was entered.
Adam Robinson
Adam's answer goes further in the explanation. If you want ASCII you can just get the value without much difficulty, but if you are looking to translate that into a digit representation, you'll have to put some work into it. Not everything will automagically translate into what you want it to.
TheTXI
This was another thing route I was trying to take. I know how to convert ASCII to int, but I wasn't sure how to get to ASCII from the Keys enum.
Andy Stampor
A: 

int i = (int)e.KeyValue;

Jeremy
Let me clarify:Using my example of the "number pad 8" above, the int value of that is 104, so my value using your code would be 104, but I really want the value to be 8.
Andy Stampor
+2  A: 

If you want NUMERIC values, you'll have to create a switch(e.KeyCode) statement and evaluate the key and create your own int. There's no simple way to turn a Keys into a numeric value that represents the number on the key. The closest you could get might be the ASCII equivalent, which would still need to be translated.

Adam Robinson
Simple math is much better than a switch for every value. Please check below.
John Fisher
You posted your own answer...it's really not necessary to comment in others in order to attract attention to your own.
Adam Robinson
Thanks Adam. But that wasn't my intent. If someone read this post and liked it, I wanted to push them away from the switch statement idea whether they found my answer or not.
John Fisher
+8  A: 

I'd go with this solution:

int value = -1;
if(e.KeyValue >= ((int)Keys.NumPad0) && e.KeyValue <= ((int)Keys.NumPad9)){ // numpad
    value = e.KeyValue - ((int)Keys.NumPad0);
}else if(e.KeyValue >= ((int)Keys.D0) && e.KeyValue <= ((int)Keys.D9)){ // regular numbers
    value = e.KeyValue - ((int)Keys.D0);
}

...if the point was to get the numeric value of the label of they key that was punched in.

Tommi Forsström
why not use the enums in place of the numbers so that it is more readable? ">= (int)Keys.D0" and ">= (int)Keys.Numpad0" etc...
Erich Mirabal
Lots of magic numbers in this code. Using the Keys.X enumerations is much clearer.
John Fisher
Good point! Thanks!
Tommi Forsström
I was thinking that very thing, but this is what I needed. Thanks!
Andy Stampor
This does not handle pressing 9
John Rasch
Yeah, the edited code missed that it was using a value one higher than the actual enum. It just needs a "<=" for both 9 conditions.
Andy Stampor
Perhaps you should initialize the value to something other than 0? How else do you know if the user pressed 0 or not?
Joseph
In my code based on what is here, I initialized to -1.
Andy Stampor
+1  A: 

Could you just listen for the KeyPress event instead? It will give the character that was actually pressed.

Samuel
You are still missing how to use that data. I assume you mean that he should use the KeyPress event and do a int.TryParse on it?
Erich Mirabal
A: 

The KeyValue represents the character code for the key that was pressed. In order to obtain its numerical valaue you should find the character for the key that was pressed, then parse it from a character to an integer.

Something like Convert.ToInt32(e.KeyCode.ToString())

Robin Day
+1  A: 

This function will do what you want:

private int GetKeyValue(int keyValue)
{
    if (keyValue >= 48 && keyValue <= 57)
    {
     return keyValue - 48;
    }
    else if (keyValue >= 96 && keyValue <= 105)
    {
     return keyValue - 96;
    }
    else
    {
     return -1; // Not a number... do whatever...
    }
}

Call it like so:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    int num = GetKeyValue(e.KeyValue); 
}
John Rasch
There is too much hard-coding in this function to be truly good code. Look below for a modified version.
John Fisher
True, but this is such a trivial function that very simple comments would inform anyone exactly what it does
John Rasch
+3  A: 

Something like this should work well: (Edited)

int keyVal = (int)e.KeyValue;
int value = -1;
if ((keyVal >= (int)Keys.D0 && keyVal <= (int)Keys.D9)
{
    value = (int)e.KeyValue - (int)Keys.D0;
}
else if (keyVal >= (int)Keys.NumPad0 && keyVal <= (int)Keys.NumPad9)
{
    value = (int)e.KeyValue - (int)Keys.NumPad0;
}
John Fisher
+1 for actually using the enums! How come nobody else wants to do that?
Erich Mirabal
you have to subtract based on the range (D0 or NumPad0, not just D0).
Erich Mirabal
Yep. I noticed that in Tommi's answer.
John Fisher
A: 

Or create a extension method and call it like

private void Form1_KeyDown(object sender, KeyEventArgs e)
{    
    int num = e.KeyValue.GetKeyValue();  
}

where the extension method is

public static class MyExtensions
{
    public static int GetKeyValue(this int keyValue)
    {

        if (keyValue >= 48 && keyValue <= 57)
        {
            return keyValue - 48;
        }
        else if (keyValue >= 96 && keyValue <= 105)
        {
            return keyValue - 96;
        }
        else
        {
            return -1; // Not a number... do whatever...    }

        }
    }
}
salgo60
A: 

Facts: Keyboard has keys. Some keys represent numbers and some do not.

Problem (rephrased): Yield a numeric value represented by a key, if the key represents a number.

To solve the problem it is necessary to know which keys (out of set of all keys) represent numbers as well as exact numeric value each (number) key represents.

To my knowledge there is no an easy way to get such a mapping from the framework.

Note: The fact D0-D9 and NumPad0-NamPad9 are sequential in the Keys enum is accidental and relying on these values being ordered sequentially is unfounded.

So solution would be: 1. Determine if given key represents a number. 2. Return numeric value of the key if key represents a number.

        private static readonly IDictionary<Keys, int> NumericKeys = 
        new Dictionary<Keys, int> {
            { Keys.D0, 0 },
            { Keys.D1, 1 },
            { Keys.D2, 2 },
            { Keys.D3, 3 },
            { Keys.D4, 4 },
            { Keys.D5, 5 },
            { Keys.D6, 6 },
            { Keys.D7, 7 },
            { Keys.D8, 8 },
            { Keys.D9, 9 },
            { Keys.NumPad0, 0 },
            { Keys.NumPad1, 1 },
            { Keys.NumPad2, 2 },
            { Keys.NumPad3, 3 },
            { Keys.NumPad4, 4 },
            { Keys.NumPad5, 5 },
            { Keys.NumPad6, 6 },
            { Keys.NumPad7, 7 },
            { Keys.NumPad8, 8 },
            { Keys.NumPad9, 9 }
    };

    private int? GetKeyNumericValue(KeyEventArgs e) {
        if (NumericKeys.ContainsKey(e.KeyCode)) return NumericKeys[e.KeyCode];
        else return null;
    }

Arguably, not the simplest solution, but the one that models the solution closely.