Re: WaitForSingleObjectEx() is broken
- From: "f0dder" <f0dder_nospam@xxxxxxxxxxxxxxxx>
- Date: Sun, 11 Sep 2005 07:18:19 +0200
hutch-- wrote:
> Alex,
>
>> What's wrong with ReadConsole?
>
> Nothing but this does not fix the problem with
> WaitForSingleObject(Ex). It is documented as being able to wait on a
> console input which it does but its recovery is so slow that it fails
> on te next iteration.
Actually WaitForSingleObject(Ex) works perfectly here, it is (as usual) your
understanding that is flawed. Here's a sample rundown of the test program
(attached later in this post) when pressing the key 'a':
Waiting for console input...
I got 1 records
input type KEY_EVENT
Down: 1, Repeat: 1, KeyCode: 65, ScanCode: 30, AsciiChar: 97,
ControlKeyState: 0
Waiting for console input...
I got 1 records
input type KEY_EVENT
Down: 0, Repeat: 1, KeyCode: 65, ScanCode: 30, AsciiChar: 97,
ControlKeyState: 0
And no, this is not a problem with FlushConsoleInputBuffer... what happens
is that the computer is a LOT faster than an average human. Your KeyDown is
detected, and the routine goes to FlushConsoleInputBuffer +
WaitForSingleObject(Ex) a LOT sooner than you can release the key. If you
keep the key pressed instead of releasing it, you will generate more events
with KeyDown and RepeatCount.
It doesn't have to do with the "latency" of any windows API, it has to do
with the fact that computers are a looooooot faster than the average human's
nervous system and muscles.
Also, try making the window lose and regain focus. Yup, triggers an event.
This doesn't count as a keyboard input in MY book. Try running test.exe with
a redirected input handle (like, "test.exe < test.cpp"). Doesn't wait for a
key either.
If the console isn't in "QuickEdit" mode, try rigth-clicking (to bring up
the menu). Then click the menu, or outside the menu. Hm, MENU_EVENT doesn't
really seem like a keypress to me.
To get mouse input events, it should be noted that these events are only
generated when the console is running in fullscreen mode (ALT+ENTER). Also,
ENABLE_MOUSE_INPUT will have to be specified in a call to SetConsoleMode
(recompile app with the line uncommented and test).
Since, I presume, hutch-- is writing a routine for generic use, he WILL have
to handle the cases where the user of his library has specified mouse input
for the console.
There is a reason that the _getch() and friends in MS libc are more than two
lines. The MS console API is pretty lowlevel and flexible, and this does
come at the price of some complexity. But of course it's easier to blame
Microsoft and write shitty, unreliable, buggy code, than it is to do things
right.
This is not the first time hutch-- has shown his ignorance on the console
input API, by the way. There was a thread about it on the masmforum where
Jibz patiently tried explaining the (same) issues to hutch. Unfortunately I
can't find the thread right now, but I wouldn't be surprised if it has been
removed because it's a "liability"...
PS: you can get multiple (and many!) input events with a single wait... try
pasting some text into the console.
Anyway, here's the test piece:
------------------------------
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
const unsigned MAX_RECORDS = 128;
static HANDLE g_hConsole;
struct ListEntry
{
unsigned id;
const char* name;
};
ListEntry EventNames[] =
{
{ KEY_EVENT, "KEY_EVENT" },
{ MOUSE_EVENT, "MOUSE_EVENT" },
{ WINDOW_BUFFER_SIZE_EVENT, "WINDOW_BUFFER_SIZE_EVENT" },
{ MENU_EVENT, "MENU_EVENT" },
{ FOCUS_EVENT, "FOCUS_EVENT" },
{ 0, 0 }
};
const char *findName(const ListEntry *list, unsigned id)
{
while(list->id)
{
if(id == list->id)
return list->name;
list++;
}
return "<unknown>";
}
void WaitForKey()
{
HANDLE hcon = g_hConsole;
INPUT_RECORD irList[MAX_RECORDS];
DWORD num_records;
printf("Waiting for console input...\n");
FlushConsoleInputBuffer(hcon);
WaitForSingleObjectEx(hcon, INFINITE, 0);
PeekConsoleInput(hcon, irList, MAX_RECORDS, &num_records);
printf("I got %d records\n", num_records);
for(unsigned i=0; i<num_records; i++)
{
KEY_EVENT_RECORD& ke = irList[i].Event.KeyEvent;
printf("input type %s\n", findName(EventNames, irList[i].EventType));
if(KEY_EVENT == irList[i].EventType)
{
printf("Down: %d, Repeat: %d, KeyCode: %d, ScanCode: %d, AsciiChar: %d,
ControlKeyState: %d\n",
ke.bKeyDown, ke.wRepeatCount, ke.wVirtualKeyCode, ke.wVirtualScanCode,
ke.uChar.AsciiChar, ke.dwControlKeyState);
}
}
}
int main()
{
g_hConsole = GetStdHandle(STD_INPUT_HANDLE);
// g_hConsole = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
// 0, OPEN_EXISTING, 0, 0);
//
// above statement is the PROPER way to do it.
SetConsoleMode(g_hConsole, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
WaitForKey();
WaitForKey();
WaitForKey();
WaitForKey();
WaitForKey();
}
.
- Follow-Ups:
- Re: WaitForSingleObjectEx() is broken
- From: f0dder
- Re: WaitForSingleObjectEx() is broken
- From: hutch--
- Re: WaitForSingleObjectEx() is broken
- References:
- Re: WaitForSingleObjectEx() is broken
- From: Hoogilan
- Re: WaitForSingleObjectEx() is broken
- From: hutch--
- Re: WaitForSingleObjectEx() is broken
- From: Alex McDonald
- Re: WaitForSingleObjectEx() is broken
- From: hutch--
- Re: WaitForSingleObjectEx() is broken
- Prev by Date: Re: WaitForSingleObjectEx() is broken
- Next by Date: Re: WaitForSingleObjectEx() is broken
- Previous by thread: Re: WaitForSingleObjectEx() is broken
- Next by thread: Re: WaitForSingleObjectEx() is broken
- Index(es):
Relevant Pages
|