In Charles Petzold's book "Programming Windows", he mentioned the following:
"Be careful with GetKeyState. It is not a real-time keyboard status check. Rather it reflects the keyboard status up to and including the current message being processed."
"Do not do while(GetKeyState(VK_F1) >= 0);", it is guaranteed to hang your program.
I don't understand these at all. Could someone give an explanation for these two facts, please.
Every time you read a queued keyboard message, for example by calling GetMessage, the OS updates private keyboard state data associated with the calling thread. When you call GetKeyState that private keyboard state data is used to determine the returned key state. Thus, so long as you don't read another queued message, GetKeyState will always return the same value.
Related
I have a thread that calls ::PostMessage(hWnd, [...]); to send a message to the main thread alerting it to the results of an async operation.
However, I'm concerned that if the thread takes a particularly long time to finish its operation, the hWnd may not exist when the PostMessage is called (the user may have closed the window).
The MSDN Documentation doesn't say anything about the results if hWnd is invalid.
Do you know from experience, or other documentation, about what I can expect if hWnd is invalid?
Raymond Chen wrote about this:
http://blogs.msdn.com/b/oldnewthing/archive/2007/07/16/3885472.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2007/07/17/3903614.aspx
Some choice excerpts:
It so happens that boatloads of programs (and "boatloads" is a technical term) contain bugs where they use window handles after the window has been destroyed. When a window handle is re-used, that program sends a message to the window it thinks is still there, but instead it sends the message to a completely unrelated window. This doesn't bode well for the program, and it usually doesn't bode well for the new window that received the message by mistake either.
We left off our story last time by raising the problem of programs that send messages to windows that have already been destroyed and how window handle re-use exacerbates the problem. Although this is clearly a bug in the programs that use window handles after destroying the window, the problem is so widespread that the window manager folks in Windows NT decided to take a more proactive approach.
As others have pointed out, Ramond Chen explained what happens if the HWND gets re-used by a new window. PostMessage() will succeed, it will just go to the wrong window. However, in cases where the HWND does not get re-used, PostMessage() will fail with an ERROR_INVALID_WINDOW_HANDLE (1400) error code.
The two key-state functions in the WIndows API, GetKeyState() and GetAsyncKeyState(), both determine key state based on key up/down messages rather than the physical state of the key.
I am working on a program which manipulates input, using SendInput(), to release modifier keys (alt, ctrl, etc...), send input, and then re-press the modifier keys.
The problem is that I don't know if the modifier keys are still pressed after the input is sent because I have sent the key-up event and both of the above mentioned functions return that the key is up regardless of the state of the physical key. So if I assume they are still down, the user is left with a dangling ctrl-down causing problems until the user presses and releases cntl again (or any modifier key). Otherwise the key may be left up even when the physical key is still down.
So is there any way (preferably without anything too low level) to detect the physical key state. Windows-only methods are fine. Key monitoring (listening for key up events) really isn't possible (or at least really, really not preferable).
You aren't giving the window manager enough time to process the input you just injected. Until it reaches the "update key states for GetAsyncKeyState" part of the code, GetAsyncKeyState will report the old value. (In particular, it won't reach that point until all low-level keyboard hooks have had a chance to inspect the action and possibly reject it.)
In other words, your code has a race condition, and that is what you are observing.
You are getting a bit confused here. In fact GetAsyncKeyState() does return the key state at the instant that GetAsyncKeyState() was called. On the other hand, GetKeyState() returns the key state based on the history of queued messages.
After much testing, I seem to have figured it out. MSDN states about GetKeyState() :
The key status returned from this function changes as a thread reads key messages from its message queue.
GetAsyncKeyState() still works on key up/down messages (not physical key state) however, it just doesn't wait for the message to be read. So if a key event message is sent via SendInput(), it will still return incorrectly - in fact, it will be incorrect before GetKeyState() because it will be incorrect immediately after the call.
A simple test to demonstrate this functionality is here (VS2010 solution) or just the source here.
This is somewhat of a general question regarding Windows programming:
Are Window messages "reliable"?
For example (these are just examples):
Can you be certain that a WM_MOUSEMOVE will happen before a cursor enters your screen?
Can you be certain that you will get a WM_DEVICECHANGE message if a device is inserted?
Can you be certain that you will receive a WM_KILLFOCUS message if your window loses focus?
Or, in other words: Can you be certain that you'll get the appropriate message at the appropriate times, or do you always have to code defensively in case that, somehow, you might miss a message for no apparently documented reason?
Example:
It is guaranteed (AFAIK) that a file system filter driver will not "miss" a file operation or change notification.
By contrast, it is not guaranteed that ReadDirectoryChangesW will not miss a notification. In fact, it can miss quite a few if its buffer overflows.
Note:
I am not talking about a situation against an adversary (e.g. someone hijacking your window procedure or installing a hook/filter); that would pretty much invalidate any guarantee. I'm only asking about obscure situations that could really happen even if no one meant anything bad intentionally, like if some random buffer overflows, if someone uses SendInput, etc., assuming you have control of your own code.
No you cannot be certain that a given message will be delivered in a specific order. Here are a couple of reasons why not
Messages can be sent progamatically and this can be used to simulate "impossible" scenarios like a WM_KEYUP followed by a WM_KEYDOWN.
Another routine could sub-class your window and selectively intercept messages and not send them on to your WNDPROC
It's best to code defensively around any scenarios where ordering is important
I've got a routine that looks something like this, in pseudocode:
while PeekMessage(Message, 0, 0, 0, PM_REMOVE)
HandleMessageAppropriately(Message)
Basically, it goes through and pulls all messages out of the queue and dispatches them. I can't change this routine.
I've got a scenario in which this routine, if it's being called under certain conditions and there's a message in the queue representing the user having hit ESC at exactly the wrong moment, it can cause the program to crash. (Gotta love race conditions.)
I can't change the routine above, but I can change the code that calls it. Is there any way that I can do something immediately before this is run that will say "go through the message queue and remove all keyboard input messages where the user hit ESC, without affecting the rest of the items in the queue or changing their order"?
You can use the range parameters in PeekMessage to restrict to the WM_CHAR message only, and PM_NOREMOVE to leave the message queue intact if the character isn't ESC; if the message needs to be removed, repeat the process with the PM_REMOVE flag. Unfortunately there's no way to look past the first WM_CHAR in the queue.
This is the exact equivalent to the infamous DoEvents call that got so many VB6 programmers in trouble. Because surely the ESC keypress is closing a window, leaving code running in a loop without a user interface anymore. The outcome is invariably poor.
You don't mess around with this, you call EnableWindow(hWnd, FALSE) before you enter this loop to disable input on the window that shouldn't be closed. Now you don't care anymore what's in the message queue. The exact same thing that dialogs do.
Don't paper over a modal loop. Make it modal, make it obvious to the user too.
You may be best to hook the call to PeekMessages and replace it with a version that does what you need.
You could use madshi's hooking routines but it's not hard - I've published a simple hook routine here on Stack Overflow.
If the code was running in an executable module that you compile then you could compile a customised version of Windows.pas that replaced PeekMessage. Of course I'm guessing that you code is Delphi.
I come from the world of web programming and usually the server sets a superglobal variable through the specified method (get, post, etc) that makes available the data a user inputs into a field. Another way is to use AJAX to register a callback method to an event that the AJAX XMLhttpRequest object will initiate once notified by the browser (I'm assuming...). So I guess my question would be if there is some sort of dispatch interface that a systems programmer's code must interact with vicariously to execute in response to user input or does the programmer control the "waiting" process directly? And if there is a dispatch is there a loop structure in an OS that waits for a particular event to occur?
I was prompted to ask this question here because I'm in a basic programming logic class and the professor won't answer such a "sophisticated" question as this one. My book gives a vague pseudocode example like:
//start
sentinel_val = 'stop';
get user_input;
while (user_input not equal to sentinel_val)
{
// do something.
get user_input;
}
//stop
This example leads me to believe 1) that if no input is received from the user the loop will continue to repeat the sequence "do something" with the old or no input until the new input magically appears and then it will repeat again with that or a null value. It seems the book has tried to use the example of priming and reading from a file to convey how a program would get data from event driven input, no?
I'm confused :(
At the lowest level, input to the computer is asynchronous-- it happens via "interrupts", which is basically something external to the CPU (a keyboard controller) sending a signal to the CPU that says "stop what you're doing and accept this data". (It's complex, but this is the general idea). So the CPU stops, grabs the keystroke, and puts it in a buffer to be read, and then continues doing what it was doing before the interrupt.
Very similar things happen with inbound network traffic, and the results of reading from a disk, etc.
At a higher level, it gets more dependent on the operating system or framework that you're using.
With keyboard input, there might be a process (application, basically) that is blocked, waiting for user input. That "block" doesn't mean the computer just sits there waiting, it lets other processes run instead. But when the keyboard result comes in, it will wake up the one who was waiting for it.
From the point of view of that waiting process, they called some function "get_next_character()" and that function returned with the character. Etc.
Frankly, how all this stuff ties together is super interesting and useful to understand. :)
An OS is driven by hardware event (called interrupt). An OS does not wait for an interrupt, instead, it execute a special instruction to put the CPU a nap in a loop. If a hardware event occurs, the corresponding interrupt will be invoked.
It seems the book has tried to use the example of priming and reading from a file
to convey how a program would get data from event driven input, no?
Yes that is what the book is doing. In fact... the unix operating system is built on the idea of abstracting all input and output of any device to look like this.
In reality most operating systems and hardware make use of interrupts that jump to what we can call a sub-routine to perform the low level data read and then return control back to the operating system.
Also on most systems many of the devices work independent of the rest of the operating system and present a high level API to the operating system. For example a keyboard port (or maybe a better example is a network card) on a computer process interrupts itself and then the keyboard driver presents the operating system with a different api. You can look at standards for devices to see what these are. If you want to know the api the keyboard port presents for example you could look at the source code for the keyboard driver in a linix distro.
A basic explanation based on my understanding...
Your get user_input pseudo function is often something like readLine. That means that the function will block until the data read contains a new line character.
Below this the OS will use interrupts (this means it's not dealing with the keyboard unessesarily, but only when required) to allow it to respond when it the user hits some keys. The keyboard interrupt will cause execution to jump to a special routine which will fill an input buffer with data from the keyboard. The OS will then allow the appropriate process - generally the active one - to use readLine functions to access this data.
There's a bunch more complexity in there but that's a simple view. If someone offers a better explanation I'll willingly bow to superior knowledge.