Solved

Overlapped keyboard input from console?

Posted on 1998-07-21
19
2,467 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 
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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

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…
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…
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…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

739 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