Sign in to follow this  

Converting Virtual Keys to Scan Codes (for DirectInput)

This topic is 4719 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Well, I found the tutorial here that describes it, but I'm running into one problem: This function doesn't work with the arrow keys (I haven't tested many other keys though). I know it works with the letters, and the shift key, but when I use VK_UP or VK_DOWN, it always returns false. Here's the function:
BYTE Keys[256]; //Keys is a buffer for a LPDIRECTINPUTDEVICE8
bool keyboard_check(UINT key) {
 return (Keys[ MapVirtualKeyEx(key,0,GetKeyboardLayout(0)) ] & 0x80);
}
I'm not sure what I did wrong. (Yes, I am looping)

Share this post


Link to post
Share on other sites
Why don't you use DIK_ constants as in http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/input/tuts/tut1/step6retrievingfromkeyboard.asp ? Maybe that's the problem.

Share this post


Link to post
Share on other sites
Well, with my game I'm going to *attempt*, I am going to make key configuration. I already have the psuedo stuff worked out on Game Maker, but I need a way to retrieve the key code (virtual is my preference) of the current key being pressed, using a loop (0-255). Plus, I have an array of strings that name each key, and uses the virtual key system (i.e. key_name[32]="Space"). It's easier to loop through with virtual key codes that it is with scan codes (I suppose).
[Sorry about replying so late]

Share this post


Link to post
Share on other sites
I've read just now the tutorial... your function is totally different if compared to the tutorial one! [oh] I can't understand why you added 0x80 (maybe you're interested in only the first 128 scan codes). Anyway you will never detect the VK_UP/VK_DOWN and other keys (such as F1, F2,...) because theese have multybyte scan code. The tutorial says "In most cases, using char(result[0]) would provide the desired output"... not in all cases! [smile] So, to solve your problem, you have to use ToAsciiEx function (as you see in the tutorial [smile]).

Hope this helps.

[Edit - added emoticons]

Share this post


Link to post
Share on other sites
For reference in case you need to manually check the numbers... I spent three hours adding a way to assign controls to keys in my old Stormrunner game (mostly with coordinate placing of the bitmap.. ugh).


Ignore blah, calc, and temp. blah & calc were the coordinates while temp was the width (normally 22).

HIGHLIGHTED, on the other hand, is what is returned by wParam when a WM_KEYDOWN event occurs.

Snippet!

//now draw the keys..
temp=22;
if(HIGHLIGHTED==VK_BACK)
{
blah=348; calc=345; temp=46;
}
else if(HIGHLIGHTED==VK_TAB)
{
blah=24; calc=369; temp=46;
}
else if(HIGHLIGHTED==VK_RETURN)
{
blah=348; calc=393; temp=70;
}
else if(HIGHLIGHTED==VK_SHIFT)
{
blah=24; calc=417; temp=71;
}
else if(HIGHLIGHTED==VK_CONTROL)
{
blah=24; calc=441; temp=46;
}
else if(HIGHLIGHTED==VK_SPACE)
{
blah=148; calc=441; temp=94;
}
else if(HIGHLIGHTED==VK_PRIOR)//page up
{
blah=474; calc=345;
}
else if(HIGHLIGHTED==VK_NEXT)//page down
{
blah=474; calc=369;
}
else if(HIGHLIGHTED==VK_DELETE)
{
blah=424; calc=369;
}
else if(HIGHLIGHTED==VK_END)
{
blah=449; calc=369;
}
else if(HIGHLIGHTED==VK_HOME)
{
blah=449; calc=345;
}
else if(HIGHLIGHTED==VK_LEFT)
{
blah=424; calc=441;
}
else if(HIGHLIGHTED==VK_UP)
{
blah=449; calc=417;
}
else if(HIGHLIGHTED==VK_RIGHT)
{
blah=474; calc=441;
}
else if(HIGHLIGHTED==VK_DOWN)
{
blah=449; calc=441;
}
else if(HIGHLIGHTED==VK_INSERT)
{
blah=424; calc=345;
}
else if(HIGHLIGHTED>47 && HIGHLIGHTED <58)//0-9
{
if(HIGHLIGHTED==48) {blah=273; calc=345;}//0
else if(HIGHLIGHTED==49) {blah=48; calc=345;}//1
else if(HIGHLIGHTED==50) {blah=73; calc=345;}//2
else if(HIGHLIGHTED==51) {blah=98; calc=345;}//3
else if(HIGHLIGHTED==52) {blah=123; calc=345;}//4
else if(HIGHLIGHTED==53) {blah=148; calc=345;}//5
else if(HIGHLIGHTED==54) {blah=173; calc=345;}//6
else if(HIGHLIGHTED==55) {blah=198; calc=345;}//7
else if(HIGHLIGHTED==56) {blah=223; calc=345;}//8
else if(HIGHLIGHTED==57) {blah=248; calc=345;}//9
}
else if(HIGHLIGHTED>64 && HIGHLIGHTED <91)//a-z
{
if(HIGHLIGHTED==65) {blah=73; calc=393;}//a
else if(HIGHLIGHTED==66) {blah=198; calc=417;}//b
else if(HIGHLIGHTED==67) {blah=148; calc=417;}//c
else if(HIGHLIGHTED==68) {blah=123; calc=393;}//d
else if(HIGHLIGHTED==69) {blah=123; calc=369;}//e
else if(HIGHLIGHTED==70) {blah=148; calc=393;}//f
else if(HIGHLIGHTED==71) {blah=173; calc=393;}//g
else if(HIGHLIGHTED==72) {blah=198; calc=393;}//h
else if(HIGHLIGHTED==73) {blah=248; calc=369;}//i
else if(HIGHLIGHTED==74) {blah=223; calc=393;}//j
else if(HIGHLIGHTED==75) {blah=248; calc=393;}//k
else if(HIGHLIGHTED==76) {blah=273; calc=393;}//l
else if(HIGHLIGHTED==77) {blah=248; calc=417;}//m
else if(HIGHLIGHTED==78) {blah=223; calc=417;}//n
else if(HIGHLIGHTED==79) {blah=273; calc=369;}//o
else if(HIGHLIGHTED==80) {blah=298; calc=369;}//p
else if(HIGHLIGHTED==81) {blah=73; calc=369;}//q
else if(HIGHLIGHTED==82) {blah=148; calc=369;}//r
else if(HIGHLIGHTED==83) {blah=98; calc=393;}//s
else if(HIGHLIGHTED==84) {blah=173; calc=369;}//t
else if(HIGHLIGHTED==85) {blah=223; calc=369;}//u
else if(HIGHLIGHTED==86) {blah=173; calc=417;}//v
else if(HIGHLIGHTED==87) {blah=98; calc=369;}//w
else if(HIGHLIGHTED==88) {blah=123; calc=417;}//x
else if(HIGHLIGHTED==89) {blah=198; calc=369;}//y
else if(HIGHLIGHTED==90) {blah=98; calc=417;}//z
}
else if(HIGHLIGHTED>95 && HIGHLIGHTED<106)//numeric keypad
{
if(HIGHLIGHTED==96) {blah=509; calc=441;}//0
else if(HIGHLIGHTED==97) {blah=509; calc=417;}//1
else if(HIGHLIGHTED==98) {blah=534; calc=417;}//2
else if(HIGHLIGHTED==99) {blah=559; calc=417;}//3
else if(HIGHLIGHTED==100) {blah=509; calc=393;}//4
else if(HIGHLIGHTED==101) {blah=534; calc=393;}//5
else if(HIGHLIGHTED==102) {blah=559; calc=393;}//6
else if(HIGHLIGHTED==103) {blah=509; calc=369;}//7
else if(HIGHLIGHTED==104) {blah=534; calc=369;}//8
else if(HIGHLIGHTED==105) {blah=559; calc=369;}//9
}
else if(HIGHLIGHTED==106)//num*
{
blah=559; calc=345;
}
else if(HIGHLIGHTED==107)//num+
{
blah=584; calc=369;
}
else if(HIGHLIGHTED==109)//num-
{
blah=584; calc=345;
}
else if(HIGHLIGHTED==110)//num.
{
blah=559; calc=441;
}
else if(HIGHLIGHTED==111)//numslash
{
blah=534; calc=345;
}
else if(HIGHLIGHTED>111 && HIGHLIGHTED<124)//Function keys
{
if(HIGHLIGHTED==112) {blah=62; calc=321;}//f1
else if(HIGHLIGHTED==113) {blah=87; calc=321;}//f2
else if(HIGHLIGHTED==114) {blah=112; calc=321;}//f3
else if(HIGHLIGHTED==115) {blah=137; calc=321;}//f4
else if(HIGHLIGHTED==116) {blah=175; calc=321;}//f5
else if(HIGHLIGHTED==117) {blah=200; calc=321;}//f6
else if(HIGHLIGHTED==118) {blah=225; calc=321;}//f7
else if(HIGHLIGHTED==119) {blah=250; calc=321;}//f8
else if(HIGHLIGHTED==120) {blah=288; calc=321;}//f9
else if(HIGHLIGHTED==121) {blah=313; calc=321;}//f10
else if(HIGHLIGHTED==122) {blah=338; calc=321;}//f11
else if(HIGHLIGHTED==123) {blah=363; calc=321;}//f12
}
else if(HIGHLIGHTED==186)//;
{
blah=298; calc=393;
}
else if(HIGHLIGHTED==187)//=
{
blah=323; calc=345;
}
else if(HIGHLIGHTED==188)//,
{
blah=273; calc=417;
}
else if(HIGHLIGHTED==189)//-
{
blah=298; calc=345;
}
else if(HIGHLIGHTED==190)//.
{
blah=298; calc=417;
}
else if(HIGHLIGHTED==191)//slash
{
blah=323; calc=417;
}
else if(HIGHLIGHTED==192)//tilde key
{
blah=24; calc=345;
}
else if(HIGHLIGHTED==219)//[
{
blah=323; calc=369;
}
else if(HIGHLIGHTED==220)//backslash
{
blah=373; calc=369;
}
else if(HIGHLIGHTED==221)//]
{
blah=348; calc=369;
}
else if(HIGHLIGHTED==222)//'
{
blah=323; calc=393;
}




-Greven

Share this post


Link to post
Share on other sites
@ deadimp:
if I were you I would give a look at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/WindowsUserInterface/UserInput/VirtualKeyCodes.asp instead of the code Evil_Greven posted. [smile]

@ Evil_Greven:
Instead of a so many lines of code [sick] you can make use of a switch statement with cases (instead of else if... else if ...). You can do yet better if you use an array:


struct
{
int blah;
int calc;
int temp;
} array[256];

array[VK_BACK].blah=348;
array[VK_BACK].calc=345;
array[VK_BACK].temp=46;




an so on.

Instead of a switch you just need theese assignments:

int myblah=array[HIGHLIGHTED].blah;
int mycalc=array[HIGHLIGHTED].calc;
int mytemp=array[HIGHLIGHTED].temp;

P.S.- HIGHLIGHTED is a var so you should write it in lowercase, just to avoid confusion with constants (in uppercase) [smile]

Share this post


Link to post
Share on other sites
Wait, I'm still kind of confused... [Sorry]
How would I use the ToAsciiEx() function to convert scan codes to virtual keys?
For example, how would I take VK_UP and get DIK_UP?
Argh! This hurts my head...
To go further, here is the code that defines the key names (it was in Game Maker Language, so ignore sytax)
//Defining Key Names
//NOTE:
//string[256] c;
//BYTE a;
//FUNCTION string string(x) { returns x as a string }
//FUNCTION string chr(x) { returns the character of Ascii value x }

c[0]="?Unknown?"
for (a=1; a<=255; a+=1;) c[a] = "<"+string(a)+">?";
//Long list
c[8]="Backspace";

c[13]="Enter";

c[16]="Shift";
c[17]="Control";
c[18]="Alt";
c[19]="Pause/Break?";
c[20]="CAPS Lock";

c[27]="Escape";

c[32]="Space";
c[33]="Page Up";
c[34]="Page Down";
c[35]="End Key";
c[36]="Home Key";
c[37]="Left";
c[38]="Up";
c[39]="Right";
c[40]="Down";
c[45]="Insert";
c[46]="Delete";
for (b=48; b<=57; b+=1;) c[b]="Number "+chr(b); //Number 0-9
for (d=65; d<=90; d+=1;) c[d]=chr(d); //A-Z
for (e=96; e<=105; e+=1;) c[e]="Numpad "+string(e-96) //Numpad 0-9
c[106]="Numpad Asterik '*'"
c[107]="Numpad Plus '+'"
c[109]="Numpad Dash '-'"
c[110]="Numpad Period '.'"
c[111]="Numpad Slash '/'"
for (f=112; f<=123; f+=1;) c[f]="F"+string(f-111) //F1-11

About the '& 0x80', in other tutorials, it returns the highest bit in the byte.

Share this post


Link to post
Share on other sites
Quote:
Original post by deadimp
Well, I found the tutorial here that describes it, but I'm running into one problem: This function doesn't work with the arrow keys (I haven't tested many other keys though). I know it works with the letters, and the shift key, but when I use VK_UP or VK_DOWN, it always returns false. Here's the function:
BYTE Keys[256]; //Keys is a buffer for a LPDIRECTINPUTDEVICE8
bool keyboard_check(UINT key) {
return (Keys[ MapVirtualKeyEx(key,0,GetKeyboardLayout(0)) ] & 0x80);
}

I'm not sure what I did wrong. (Yes, I am looping)


I have just written my input library and I came across the same problem. It so happens that certain keys, (VK_ UP,DOWN,LEFT,RIGHT,KeyPad Enter) do not translate correctly with any MapVirtualKey - here was my simple fix that I will eventuallly try and make better, but it works for now:

[CODE]
// Convert to ascii
BYTE ASCII = MapVirtualKeyEx( m_keyboardbuffer [ dwCurbuffer ].dwOfs, 1, m_layout );
if( ASCII == 0 )
{
int temp = m_keyboardbuffer [ dwCurbuffer ].dwOfs;
if( temp == DIK_LEFT )
ASCII = INPUT_LEFT;
else if( temp == DIK_RIGHT )
ASCII = INPUT_RIGHT;
else if( temp == DIK_UP )
ASCII = INPUT_UP;
else if( temp == DIK_DOWN
ASCII = INPUT_DOWN;
...
}
...
[/code]

Basically I am checking if the key I convert from DI is 0, than see if it is something that does not translate, such as those DIK_ arrow keys. The INPUT_ keys are my own defines that translate to VK_'s.

I hope this helps some.

Share this post


Link to post
Share on other sites
Quote:
Original post by deadimp
Well, I found the tutorial here that describes it, but I'm running into one problem: This function doesn't work with the arrow keys (I haven't tested many other keys though). I know it works with the letters, and the shift key, but when I use VK_UP or VK_DOWN, it always returns false. Here's the function:
BYTE Keys[256]; //Keys is a buffer for a LPDIRECTINPUTDEVICE8
bool keyboard_check(UINT key) {
return (Keys[ MapVirtualKeyEx(key,0,GetKeyboardLayout(0)) ] & 0x80);
}

I'm not sure what I did wrong. (Yes, I am looping)


I have just written my input library and I came across the same problem. It so happens that certain keys, (VK_ UP,DOWN,LEFT,RIGHT,KeyPad Enter) do not translate correctly with any MapVirtualKey - here was my simple fix that I will eventuallly try and make better, but it works for now:


// Convert to ascii
BYTE ASCII = MapVirtualKeyEx( m_keyboardbuffer [ dwCurbuffer ].dwOfs, 1, m_layout );
if( ASCII == 0 )
{
int temp = m_keyboardbuffer [ dwCurbuffer ].dwOfs;
if( temp == DIK_LEFT )
ASCII = INPUT_LEFT;
else if( temp == DIK_RIGHT )
ASCII = INPUT_RIGHT;
else if( temp == DIK_UP )
ASCII = INPUT_UP;
else if( temp == DIK_DOWN
ASCII = INPUT_DOWN;
...
}
...


Basically I am checking if the key I convert from DI is 0, than see if it is something that does not translate, such as those DIK_ arrow keys. The INPUT_ keys are my own defines that translate to VK_'s.

I hope this helps some.

- Drew

Share this post


Link to post
Share on other sites
You don't even really need to do that. Just use the DIK constants. The snippet in that article is only useful if you're using DirectInput and you want the user to be able to type strings in your game (e.g. type in their name). The DIK constants don't map easily to ASCII characters so you'd either need a massive switch statement or you'd use the function that the article presents. But for general keyboard use (i.e. movement, firing, etc) you can just use the DIK constants.

cheers
sam.

Share this post


Link to post
Share on other sites

This topic is 4719 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this