Solved

Overlapped keyboard input from console?

Posted on 1998-07-21
19
2,444 Views
Last Modified: 2013-12-03
Is it possible to do some overlapped keyboard input from a console window in Windows NT?

What I am trying to accomplish here is a little like the terminal principle.  I have one handle for a communications port, opened for OVERLAPPED operations.  Then I'd like to create another OVERLAPPED handle to the keyboard.  With both OVERLAPPED structures set with manual reset events, this would allow me to perform a WaitForMultipleObject, which would block until either the user input a keystroke or a byte arrived on the port.  I would then be able to act accordingly (i.e. send the keystroke to the port if it's a keyboard event, or output the byte received from the port to the console).  Essentially, it's the terminal principle, but SINGLE threaded.  I know this could easily be done multi-threaded (and I've done it) but now I am trying to also do a single threaded program which would be the equivalent.

When you use GetStdHandle to get a handle to stdin, there is no OVERLAPPED struct initialization, so every read from the keyboard will block.  Also, when you do a CreateFile on CONIN$, the Microsoft Win32 Reference says the dwFlagsAndAttributes parameter is ignored, keeping me from using FILE_FLAG_OVERLAPPED to enable overlapping operations.

Am I the first one to try this?  I would be grateful if somebody could point out a working solution, without polling if possible.
0
Comment
Question by:asselins
  • 12
  • 7
19 Comments
 

Author Comment

by:asselins
ID: 1410683
Adjusted points to 100
0
 
LVL 2

Expert Comment

by:abesoft
ID: 1410684
You should be able to use WaitForMultipleEventsEx.  From the docs:
The WaitForMultipleObjectsEx function can specify handles of any of the following object types in the lpHandles array:

Console input: The handle is returned by the CreateFile function when the CONIN$ value is specified, or by the GetStdHandle function. The object's state is signaled when there is unread input in the console's input buffer, and it is nonsignaled when the input buffer is empty.

Hope this helps...
0
 
LVL 2

Expert Comment

by:abesoft
ID: 1410685
Sorry, I said "WaitForMultipleEventsEx", when I should have used "WaitForMultipleObjects" or "WaitForMultipleObjectsEx"

I don't know why, but I always use the wrong name for this/these functions.  I guess it's a mental block...
0
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 2

Expert Comment

by:abesoft
ID: 1410686
I guess the real answer is that you don't need to make console input overlapped.
0
 

Author Comment

by:asselins
ID: 1410687
What do you mean?  If I don't use overlapped operations, the read on keyboard will block until there are chars to read, and this blocking operation will prevent the asynchronous reception of characters on the other input (port).

I will try your proposed answer and get back to you.
0
 

Author Comment

by:asselins
ID: 1410688
Okay, I get your last remark now.  You meant I don't need to use an OVERLAPPED structure.  You seem to be right.  I'll get back to you.
0
 

Author Comment

by:asselins
ID: 1410689
Okay, I get your last remark now.  You meant I don't need to use an OVERLAPPED structure.  You seem to be right.  I'll get back to you.
0
 

Author Comment

by:asselins
ID: 1410690
Okay, I get your last remark now.  You meant I don't need to use an OVERLAPPED structure.  You seem to be right.  I'll get back to you.
0
 

Author Comment

by:asselins
ID: 1410691
From what I've been able to test up to now, it seems the WaitForMultipleObjects always returns immediately with the handle to stdin signaled.  Then when I do a ReadFile on it, it blocks because there are no characters in the buffer.
0
 

Author Comment

by:asselins
ID: 1410692
Adjusted points to 125
0
 
LVL 2

Expert Comment

by:abesoft
ID: 1410693
ReadFile reads until the number of bytes requested have been read, or EOF is reached.  How many bytes are you requesting in the call to ReadFile?
0
 

Author Comment

by:asselins
ID: 1410694
I request 1 byte, which should be a single key.  The problem is the wait returned immediately because the GetStdHandle handle was signaled, and according to the MS ref you pointed out to me, if this handle is signaled, there should be keys ready in the buffer.

Which seems not to be the case, because the ReadFile for 1 byte blocks waiting for a key.  While this blocking operation is in progress, I cannot check the status of the other handle (a com port handle).  If you want my test source code, I can send it to you.  You might find something...

Thanks for replying, btw...
0
 
LVL 2

Expert Comment

by:abesoft
ID: 1410695
The code might help, if you can send it to abesoft@cgo.wave.ca.

Can you use things like getch(), etc to get input from the kbd?
0
 

Author Comment

by:asselins
ID: 1410696
I could use getch(), but it's hardly portable, and I'm not sure it would get input from my keyboard buffer.

I'm going to send you the source right away.
0
 

Author Comment

by:asselins
ID: 1410697
I could use getch(), but it's hardly portable, and I'm not sure it would get input from my keyboard buffer.

I'm going to send you the source right away.
0
 

Author Comment

by:asselins
ID: 1410698
Sorry about the repeating comments.  My browser seems to repost form data automatically to update the page...
0
 
LVL 2

Accepted Solution

by:
abesoft earned 150 total points
ID: 1410699
The problem comes from your mouse.  Try the following code snippet instead of your main():

int main(int argc, char *argv[])
{
    int fin = 0;
    DWORD dwWaitResult = 0;
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    if(hStdin == INVALID_HANDLE_VALUE)
    {
        ...
    }
    while (!fin)
    {
        hWaitHandles[0] = hStdin;
        dwWaitResult = WaitForMultipleObjects(
            1,                        /* 1 handles in event handle array */
            hWaitHandles,      /* event handle array */
            FALSE,                  /* return when either event is signaled */
            INFINITE            /* wait indefinitely */
            );
        if(dwWaitResult == WAIT_OBJECT_0)
        {
            if (!_kbhit())
                _putch( '.');
            else if (_getch() == ' ')
                fin = 1;
            FlushConsoleInputBuffer( hStdin);
        }
    }
    return 1;
}

This routine spits out a . whenever the console is signalled, and you can see that it is highly related to mouse movement.  Try using ReadConsole, and that should solve your problem.  

(I tried to disable mouse input on your hStdin, using SetConsoleMode, but it didn't work.  You might have more luck than I did, though.)
0
 
LVL 2

Expert Comment

by:abesoft
ID: 1410700
The more complete (succinct) explanation is that mouse movement or keyboard input will signal a console.  You will have to deal with both types of activity, unless you can mask out mouse signals.
0
 

Author Comment

by:asselins
ID: 1410701
Yes, that seems to be the case.  Actually, the console receives all kinds of events: keyboard, mouse, window buffer size, menu and focus events all wake up the wait operation.

What I had to do was use the ReadConsoleInput (ReadConsole won't do because it is the equivalent of ReadFile) to fill INPUT_RECORD structures corresponding to the signalling events when the wait returns.  With these structures, I can then determine which of the above types of operation occured, and act only in the case of a KEY_EVENT with a bKeyDown equal to TRUE.  Then I can go back to the wait after ignoring all other kinds of events.

Thanks a lot for your time, abesoft.  If you want a working code example, let me know.
0

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

As more and more people are shifting to the latest .Net frameworks, the windows presentation framework is gaining importance by the day. Many people are now turning to WPF controls to provide a rich user experience. I have been using WPF controls fo…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

790 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question