Sign in to follow this  
simpler

DirectX getting keyPressed

Recommended Posts

I got some problem with detecting if a key was pressed. It works fine with cheking if a key is down, but I want to determine if a key only was pressed.

For the key down I've done this:

bool DirectInput::keyDown(char key)
{
return (mKeyboardState[key] & 0x80) != 0;
}

if(gDInput->keyDown(DIK_W))
MessageBox(0, "W down!", 0, 0);


Which is kinda not want I want in a menu..
If anyone can show me how to get if a key is pressed, please tell me! :)

Share this post


Link to post
Share on other sites
I solved this problem by maintaining two keyboard states. One represents the current state the other one represents the last state.


return (m_keystate[key] && !m_lkeystate[key]);



I hope you get the idea behind this system.

Share this post


Link to post
Share on other sites
Or you could try using something like the following :-


bool DirectInput::keyDown(char key)
{
if(!isPressed)
{
isPressed = (mKeyboardState[key] & 0x80);
}

return isPressed;
}

bool DirectInput::keyUp(char key)
{
isPressed = (mKeyboardState[key] & 0x80);
}




Share this post


Link to post
Share on other sites
Quote:
Original post by Soul Reaver
I solved this problem by maintaining two keyboard states. One represents the current state the other one represents the last state.

*** Source Snippet Removed ***

I hope you get the idea behind this system.


That sounds like a good idea. I feel a bit confused though, how did you store the last keyboard state? I mean, the first time the function is called what value is last keyboard state then?

You have to change some in the poll() function as well, right?
Mine looks like this now:

poll()
{
// Poll keyboard.
HRESULT hr = mKeyboard->GetDeviceState(sizeof(mKeyboardState), (void**)&mKeyboardState);
if( FAILED(hr) )
{
// Keyboard lost, zero out keyboard data structure.
ZeroMemory(mKeyboardState, sizeof(mKeyboardState));

// Try to acquire for next time we poll.
hr = mKeyboard->Acquire();
}


What to add?

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Isn't this exactly what WM_KEYDOWN is for? And if you're doing text input, things get a whole lot more difficult to do correctly (And is why you should use WM_CHAR)


Okey but don't I have to check that in the msgProc() function?
Like a case statement? I don't have much experience with using the windows methods, if you will please explain for me how to do it with WM_KEYDOWN

Share this post


Link to post
Share on other sites
Quote:
Original post by simpler
Okey but don't I have to check that in the msgProc() function?
Like a case statement? I don't have much experience with using the windows methods, if you will please explain for me how to do it with WM_KEYDOWN
You get a WM_KEYDOWN message in your window proc when a key is initially pressed, and a WM_KEYUP when it's released. You also get WM_KEYDOWN messages when the key-repeat kicks in, something you'd have to do yourself with DirectInput.

What exactly are you trying to do? What do you mean "Which is kinda not want I want in a menu" - do you mean you don't want to go through and check each key whenever you check for menu options being selected? If so, you could use a std::map to map from keys to function pointer / functor or something, and then when you detect a key is pressed, look up that key in the map and call the function / functor to do the work.

Share this post


Link to post
Share on other sites
What I mean with "Which is kinda not want I want in a menu" is how my menu should work. I don't want a user being able to hold down the down key and then the menu "selector" rapidly loops through the whole many in the same speed as a while() loop goes.

I want to prevent so that the user have to "press down->release->press down again" in order to move down in the menu.

Quote:
You get a WM_KEYDOWN message in your window proc when a key is initially pressed, and a WM_KEYUP when it's released.


Okey I get a WM_KEYDOWN message in my window proc. But my menu class doesn't have any connections what so ever with the window proc function.. I can ofcourse reconstruct it up so it has, but it feels more natural to add a function to the Menu class that keeps track of if any keys have been pressed.

For example I don't want to move the "menu selector" if I'm playing a map, that means that my window proc function have to get that information and when i think about it really thinks like messing stuff up ..

It must be hard for you to understand since you don't know how I've built all my classes but I simply want is a Menu::onPress(char key) function that returns true if the 'key' have been pressed.

Share this post


Link to post
Share on other sites
It sounds like you want the std::map functor method then. Your window can keep the std::map and call the function / functor when a key is pressed.

Alternatively, just keep two arrays of bools, the keyboard state this frame, and the state last frame. Then your menu class can check if a key is pressed this frame and not pressed the last frame.

Share this post


Link to post
Share on other sites
Don't get much about std::map

Anyways, you think this code will do for storing 2 keyboardstates?

poll()
{
// Poll keyboard.
HRESULT hr = mKeyboard->GetDeviceState(sizeof(mLastKeyboardState), (void**)&mKeyboardState);
HRESULT hr = mKeyboard->GetDeviceState(sizeof(mKeyboardState), (void**)&mKeyboardState);

if( FAILED(hr) )
{
// Keyboard lost, zero out keyboard data structure.
ZeroMemory(mKeyboardState, sizeof(mKeyboardState));

// Try to acquire for next time we poll.
hr = mKeyboard->Acquire();
}


And then in Menu::keyPressed(char key)
I check if mLastKeyboardState[key] is false and mKeyboardState[key] is true.

I'm not sure how the poll() function is suppose to look like, dunno if that I posted is valid. Think it is?

Share this post


Link to post
Share on other sites
What you want is more like:
poll()
{
// Store old state
memcpy(mLastKeyboardState, mKeyboardState, sizeof(mKeyboardState));

// Poll keyboard.
HRESULT hr = mKeyboard->GetDeviceState(sizeof(mKeyboardState), (void**)&mKeyboardState);

...
You don't want to poll the keyboard twice, just store the state from the previous frame.

Share this post


Link to post
Share on other sites
If you want to, just do a poll() once in your initialization code, before any objects call poll(), to set mKeyboardState. Yes, when the first time memcpy is executed, it will copy garbage-to-garbage but the next call to poll() will save the initial state.

However, it's likely your program will execute poll() several times before the user has a chance to press a key and all will be well in any case.

Share this post


Link to post
Share on other sites
A big <3 to Evil Steve and all who helped me. I got it to work just like I wanted with this code:


void DirectInput::poll()
{
// Poll keyboard.
memcpy(mLastKeyboardState, mKeyboardState, sizeof(mKeyboardState));
HRESULT hr = mKeyboard-&gt;GetDeviceState(sizeof(mKeyboardState), (void**)&mKeyboardState);
...
}


bool DirectInput::keyPressed(char key)
{
return (!mLastKeyboardState[key] && mKeyboardState[key] & 0x80 ) != 0;
}


Thanks alot![grin]

Share this post


Link to post
Share on other sites

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