|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| Need help with how to keep track of what keys have been pressed/released in WIN32. |
|
![]() chadsxe Member since: 1/6/2006 From: Chicago, IL, United States |
||||
|
|
||||
| Hi, I am trying to create a buffer of the keys that are being pressed and released in WIN32. Currently I have.. void Input::ReadInput(MSG &msg) { switch(msg.message) { case WM_KEYDOWN: // Need to keep track of all the keys that are down break; case WM_KEYUP: // Then need to keep track of when they are released break; } } Regards Chad |
||||
|
||||
![]() jpetrie Moderator - For Beginners Member since: 6/11/2003 From: Redmond, WA, United States |
||||
|
|
||||
| Read the documentation for WM_KEYDOWN to see how you can find out which key was pressed. [Edited by - jpetrie on November 3, 2009 4:14:46 PM] Josh Petrie | Scientific Ninja | Twitter | SlimDX: October is the new August. |
||||
|
||||
![]() chadsxe Member since: 1/6/2006 From: Chicago, IL, United States |
||||
|
|
||||
| Your first link is broke. Also, what are you referencing when you said "October is the new August". Regards Chad |
||||
|
||||
![]() extralongpants GDNet+ Member since: 5/29/2002 From: Santa Ana, CA, United States |
||||
|
|
||||
Unless I'm misunderstanding your problem, you shouldn't need to check every key every time you get a msg.void Input::ReadInput(MSG &msg, bool keyStates[]) { switch(msg.message) { case WM_KEYDOWN: keyStates[msg.wParam] = true; break; case WM_KEYUP: keyStates[msg.wParam] = false; break; } } Just make sure the key state array has a lifetime that spans the length of the application (or when the user can use the keyboard), and make sure that your array is big enough to be indexed by any of the virtual key codes (or use a re-sizable vector or whatnot). [EDIT] - typos galore |
||||
|
||||
![]() chadsxe Member since: 1/6/2006 From: Chicago, IL, United States |
||||
|
|
||||
Quote: Do you mean to make one state true and one false? |
||||
|
||||
![]() extralongpants GDNet+ Member since: 5/29/2002 From: Santa Ana, CA, United States |
||||
|
|
||||
Quote: Hehe, yes, sorry about that. |
||||
|
||||
![]() jouley Member since: 4/5/2006 From: Chapel Hill, NC, United States |
||||
|
|
||||
Quote: To step in, it's due to a missing double-quote character. The post should read like this: Quote: (I've made note of this bug here, but it still plagues all forms of life!) Quote: Everything that shows up in the post after "... documentation for" is part of jpetrie's signature, that particular bit is referencing the mutability of real-world schedules ![]() |
||||
|
||||
![]() chadsxe Member since: 1/6/2006 From: Chicago, IL, United States |
||||
|
|
||||
So i got the virtual keys working just fine. I am now trying to figure out a clean way to process the A-Z 0-9 keys. THis is what I havevoid Input::ReadInput(MSG &msg) { switch(msg.message) { case WM_KEYDOWN: // Need to keep track of all the keys that are down m_keyState[msg.wParam] = true; break; case WM_KEYUP: // Then need to keep track of when they are released m_keyState[msg.wParam] = false; break; // Need to figure out how to process a-z 0-9 } } bool Input::GetKeyPress(unsigned char Num) { if(m_keyState[Num] == true) return true; return false; } Regards. Chad |
||||
|
||||
![]() extralongpants GDNet+ Member since: 5/29/2002 From: Santa Ana, CA, United States |
||||
|
|
||||
| Windows will send WM_KEYDOWN and WM_KEYUP for all the keys, including a-z and 0-9. If you put a breakpoint on your keydown handler, you should hit it when you press one of those keys. When checking whether a key is pressed or not, you have to pass the virtual key code (e.g. VK_A, VK_0), not the character value it represents. If you are referring to getting the character data that those keys generate, look into the TranslateMessage function and the WM_CHAR message. |
||||
|
||||
![]() chadsxe Member since: 1/6/2006 From: Chicago, IL, United States |
||||
|
|
||||
| Ok...I did some testing and i am having issues with WM_KEYDOWN. It is not catching all keystrokes. I have run my program through the debugger a few times now. 1st test - Set a break boint inside the WM_KEYDOWN case. This way I can see when it was being entered. It was only being entered on certain keys I was hitting. For example the arrow keys would trigger the break point but none of the character keys (A-Z 0-9) were working. For that matter a lot of the keys were not working (NumPad - F1 Key etc.). I did this test a couple times to make sure the exact same result happened. 2nd test - I moved the break point into the WM_KEYUP case. This trigger every key release that I did on the keyboard. Any ideas? Regards Chad |
||||
|
||||
![]() jpetrie Moderator - For Beginners Member since: 6/11/2003 From: Redmond, WA, United States |
||||
|
|
||||
Quote: Yup, I missed a quote. Josh Petrie | Scientific Ninja | Twitter | SlimDX: October is the new August. |
||||
|
||||
![]() extralongpants GDNet+ Member since: 5/29/2002 From: Santa Ana, CA, United States |
||||
|
|
||||
| Is somebody above your Input::ReadInput function calling TranslateMessage already? If you add a WM_CHAR message event handler to your ReadInput method, and find that you get events for those keys, it means some one is calling TranslateMessage on your WM_KEYDOWN events and skipping the call to ReadInput. What does the code that calls ReadInput look like? |
||||
|
||||
![]() chadsxe Member since: 1/6/2006 From: Chicago, IL, United States |
||||
|
|
||||
It is called inside my actual loop like so// If the message is WM_QUIT, exit the while loop while(msg.message != WM_QUIT) { if(PeekMessage(&msg,NULL,0,0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { // Update the input object m_input.ReadInput(msg); } } Regards Chad |
||||
|
||||
![]() extralongpants GDNet+ Member since: 5/29/2002 From: Santa Ana, CA, United States |
||||
|
|
||||
Wait, so what does the code that calls that code look like? |
||||
|
||||
![]() extralongpants GDNet+ Member since: 5/29/2002 From: Santa Ana, CA, United States |
||||
|
|
||||
| I suspect something is wrong with that loop. PeekMessage gets the next message from the queue. Having if (msg.message != WM_QUIT) above that means you're examining a message before it has been initialized. Basically, what your code is saying is, "If I successfully get a message, translate and dispatch it, otherwise, let my input class handle the event", which means your ReadInput method only ever gets called when there are no messages in the queue - not what you want. Since you create your MSG instance outside the loop, this effectively means that your ReadInput method only gets called with the last handled event in the queue each update cycle. |
||||
|
||||
![]() chadsxe Member since: 1/6/2006 From: Chicago, IL, United States |
||||
|
|
||||
bool Application::Run() { if (Init() == true) { // display the window on the screen ShowWindow(m_window, SW_NORMAL); UpdateWindow( m_window ); MSG msg; // message from window ZeroMemory(&msg, sizeof(MSG)); // If the message is WM_QUIT, exit the while loop while(msg.message != WM_QUIT) { if(PeekMessage(&msg,NULL,0,0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { // Update the input object m_input.ReadInput(msg); // Begin the scene. m_graphics.ClearDisplay(); m_graphics.BeginScene(); // End the scene and present it. m_graphics.EndScene(); m_graphics.Present(); // Do per-frame processing, break on false return value if(Frame() == false){ break; } } } } // Shutdown all components Shutdown(); // Kill Window UnregisterClass(m_className.c_str(),GetModuleHandle(NULL)); return true; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { // Create our game object Game game; // Initialize engine if ( FAILED ( game.InitializeEngine(hInstance) ) ) return 0; // And run it until it returns return game.Run(); } The "Game" class inherits from the Application class. Also, I moved my call to ReadInput just before TranslateMessage and it seems to be working. Regards Chad |
||||
|
||||
![]() extralongpants GDNet+ Member since: 5/29/2002 From: Santa Ana, CA, United States |
||||
|
|
||||
| Your run loop looks like it's only going to process one MSG every frame, which may cause messages to build up in the queue and be handled one or more frames later than they could/should be. You should probably loop every frame on PeekMessage until the message queue is empty, then do your game/rendering updates after that. |
||||
|
||||
![]() chadsxe Member since: 1/6/2006 From: Chicago, IL, United States |
||||
|
|
||||
Quote: I am having a hard time following you. Care to offer up some more insight? :) From what I gather is this not what my loop actually does. As it passes through it checks if the message queue is not empty. "If" PeekMessage says there is something there then it retrives with and I would deal with it. Only "if" PeekMessage says there is nothing then I do my rendering. I am so confused. haha Regards Chad |
||||
|
||||
![]() extralongpants GDNet+ Member since: 5/29/2002 From: Santa Ana, CA, United States |
||||
|
|
||||
Basically, I think your loop should look more like this:while (true) { while (PeekMessage(...)) { // ReadInput, translate, dispatch } // update, render, etc. } This way you are emptying the event queue every frame, and responding to every event in a timely fashion. |
||||
|
||||
![]() chadsxe Member since: 1/6/2006 From: Chicago, IL, United States |
||||
|
|
||||
Quote: Yeah I was starting to gather this after looking closer at my code. Thanks for the help. Regards Chad |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|