Sign in to follow this  

Keyboard input with windows

This topic is 4728 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

To get keyboard input in OpenGL, I'm using the way that is shown in nehe's tutorials. My current problem is that when I press a key, even if I press it as quickly as I can, it types the character 3 times. I'm assuming that I should use some kind of timer and then accept new input only after the timer resets, but I'm at a bit of a loss. Can anyone give me a couple of ideas that have worked for them?

Share this post


Link to post
Share on other sites
The easiest way to do this is to have two arrays of bools (256 elements for all keys). One array will keep track of which keys are currently down and the other will keep track of which keys were clicked (not previously down).

When you get a WM_KEYDOWN message first check your array of keys, if the key is already stored as down then its a repeat, otherwise set clicked to true. Update the key down status to true aswell.

On WM_KEYUP just reset the stat for the down (false).

With this method you will need to reset the clicked states of each key at the end of your loop, simple for loop with do it.

Well thats one way of doing it, there are probably others so this might not be the best

HTH anyway

Share this post


Link to post
Share on other sites
Quote:
Original post by Endar
To get keyboard input in OpenGL, I'm using the way that is shown in nehe's tutorials.

My current problem is that when I press a key, even if I press it as quickly as I can, it types the character 3 times. I'm assuming that I should use some kind of timer and then accept new input only after the timer resets, but I'm at a bit of a loss.

Can anyone give me a couple of ideas that have worked for them?


Here's something you can try. After you process the key - set it to 0. Here is an example:

if ( keys['A'] ) // test to see if A was pressed
{
... your code ...
keys['A'] = 0;
}

Do this for all your events - or just make a Clear function that does it for you.

void ClearKey( int key)
{
leys[key] = 0;
}

I hope this helps!

Share this post


Link to post
Share on other sites
OpenGL or not you have to use the standard Windows API...no need for DInput to do so!
You can use Windows message or you can use this asyncronous method (that I prefer)

If you use C++ I suggest you to put everything in your own class (typedef, inline functions,...)

You need two SHORT array to track keyboard input


typedef SHORT WINKEYBSTATE[256];
typedef SHORT* LPWINKEYBSTATE;

LPWINKEYBSTATE pck; // ptr to (c)urrent kstate
LPWINKEYBSTATE pok; // ptr to (o)ld kstate

...

WINKEYBSTATE ks1; // state 1
WINKEYBSTATE ks2; // state 2



Init them


GetKeyboardState(ks1);
memcpy(ks2,ks1,sizeof(WINKEYBSTATE));
pck = ks1;
pok = ks2;



where


void GetKeyboardState(LPWINKEYBSTATE pks)
{
for(int vk=0;vk<256; vk++){
pks[vk]=GetKeyState(vk);
}
}

SHORT GetKeyState(BYTE vkey){
return(GetAsyncKeyState(vkey)); // windows API func
}



before or after your rendering/idle phase, read the keyboard this way


// swap current with old (simply swap ptr)
LPWINKEYBSTATE tmp = pck;
pck = pok;
pok = tmp;

// refresh current state
GetKeyboardState(pck);



To make your tests use these functions


bool KeyDown(BYTE vkey){
return(KeyDown(pck,vkey)); // see after
}

bool KeyUp(BYTE vkey){
return(KeyUp(pck,vkey));
}

bool KeyPressed(BYTE vkey){
return(KeyUp(pok,vkey)&&KeyDown(pck,vkey)); // was up , is down
}

bool KeyReleased(BYTE vkey){
return(KeyDown(pok,vkey)&&KeyUp(pck,vkey)); // was down, is up
}

bool KeyDown(LPWINKEYBSTATE pk, BYTE vkey){
return((pk[vkey]&DOWNMASK)!=0);
}

bool KeyUp(LPWINKEYBSTATE pk, BYTE vkey){
return(!KeyDown(pk,vkey));
}



where


SHORT DOWNMASK = (SHORT)(1<<(8*sizeof(SHORT)-1));



and vkey is a virtual key code (VK_UP, VK_0, VK_PRIOR, ...)

You can use Windows API to convert from/to them


UINT ToChar(BYTE vkey){
return((unsigned char)MapVirtualKey(vkey,2));
}

SHORT ToVkey(unsigned char ch){
return((BYTE)VkKeyScan(ch)); // you need only low word bits
}



I'm sure it will resolve your problems...of course it seems more difficult but you need to write it once!

Ciao

Share this post


Link to post
Share on other sites

This topic is 4728 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