Solved

Overlapped keyboard input from console?

Posted on 1998-07-21
19
2,427 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
 
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

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

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

This tutorial is about how to put some of your C++ program's functionality into a standard DLL, and how to make working with the EXE and the DLL simple and seamless.   We'll be using Microsoft Visual Studio 2008 and we will cut out the noise; that i…
If you have ever found yourself doing a repetitive action with the mouse and keyboard, and if you have even a little programming experience, there is a good chance that you can use a text editor to whip together a sort of macro to automate the proce…
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…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

757 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now