How to process WM_KEYDOWN, WM_KEYUP?

Started by
3 comments, last by Buckeye 14 years, 3 months ago
Hello everybody and best wishes for a merry Christmas. I'd like to ask you how I should optimally process WM_KEYDOWN and WM_KEYUP messages. Bassed on tutorial #1 by nehe what I do so far is I create an array of bools keys[256], and then do the following in the message handler function: case WM_KEYDOWN: { keys[wParam] = TRUE; return 0; } case WM_KEYUP: { keys[wParam] = FALSE; return 0; } Then I check for key presses in the message loop after TranslateMessage and DispatchMessage if(keys[VK_ESCAPE)] { SendMessage(GetActiveWindow(), WM_CLOSE, 0, 0); } Now what I was expecting was that every time I would press ESC or another key immediately 2 messages would be sent to the queue one after another WM_KEYDOWN,WM_KEYUP. What really happens though is that the message handler only processes WM_KEYDOWN setting the TRUE the key in the keys array but WM_KEYUP is never processed thus although i release the key this is never unflagged in the keys array(set back to FALSE). As a result if I select not to quit (by a messagebox when the WM_CLOSE message is processed) my program keeps posting WM_CLOSE again and again thus i'm always asked if i want to quit. SO since this simple approach doesn't seem to work I'd like to ask your advice. I know someone would propose to set a key back to FALSE right after WM_KEYDOWN is processed. But I think this is not a good structured approach. This way we would be ignoring the WM_KEYUP message, right? Thanks in advance for your posts!
Advertisement
Quote:But I think this is not a good structured approach.

Why do you think that's not a good approach?

However, first, you need to find out why you're not processing WM_KEYUP messages properly. They are being sent to your messageloop.

Output console or debug messages when WM_KEYUP is received, along with the value of the wParam and check that you're setting and checking the correct flag.


[Edited by - Buckeye on December 23, 2009 7:37:48 AM]

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Hi again,

I reexamined this problem and found out that my WM_KEYUP messages are not received when I have a messagebox announcing something before.

For example, If I have a messagebox show up for both WM_KEYDOWN and WM_KEYUP showing up in my message handler, then when I press a key during runtime I only get a "Button Pressed", I press OK and that's it. The WM_KEYUP message seems to have been lost!

On the other hand if I removce the messagebox from WM_KEYDOWN then the WM_KEYUP message is received and I get the corresponding "Button Released".

Why are the messages lost due to a mailbox? Will using the GetKeyState() or GetAsynchState() functions yield any better results?

thanx
Call me crazy if I'm wrong, as I don't fully know the intracacies of the Windows message loop, but a MessageBox puts up a modal dialog box that steals focus from the rest of the program, effectively halting all execution on the UI thread until it is done away with.

How are you verifying that you're missing the key up messages? If you're waiting for a messagebox to pop up for it, but there's already an active one for the keydown, you'll be waiting a very long time. Another dialog can't show on the same thread of execution while a modal dialog is up.

That is one of the many reasons I hate modal dialog boxes in software in general, though as a debugging tool they can make sense sometimes.
From the documentation: "The WM_KEYUP message is posted to the window with the keyboard focus when a nonsystem key is released."

If you open a messagebox (a window) on WM_KEYDOWN, the WM_KEYUP message is probably sent to the messagebox, not your application window. The message isn't lost.

Back to your statement about resetting a flag when you process the information: "I think this is not a good structured approach." If you're not interested in WM_KEYUP for VK_ESCAPE, why wouldn't you reset the flag?

It's actually good practice to reset flags when they're processed, if you want to indicate you've processed the information and you're not interested in maintaining that information. You do that in your message loop by returning 0 when you process a message. Why wouldn't you do it elsewhere?

If you are interested in keeping track of the state of a key and there's a possibility that window focus will change, you can use GetAsyncKeyState().

Don't use GetKeyState(). From the documentation: "The key status returned from this function changes as a thread reads key messages from its message queue. The status does not reflect the interrupt-level state associated with the hardware. Use the GetAsyncKeyState function to retrieve that information." (Emphasis mine).

However, it appears you're not interested in whether Esc was released, only when it's pressed. So why add code to process information you're not interested in?

EDIT: By the way, you are correct that the WM_KEYUP is not received by your application. I did a quick test and, indeed, it's not received. As mentioned above, it probably goes to the messagebox.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement