Thread: portable getch( )

  1. #1
    VA National Guard The Brain's Avatar
    Join Date
    May 2004
    Location
    Manassas, VA USA
    Posts
    903

    portable getch( )

    Trying to make my own version of getch( ) that will work like <conio.h>'s getch( ) where a character can be removed from the keyboard buffer without having to wait for a newline/carriage return.

    Here is what I've come up with so far. The code looks like it should work; however, the program does not seem to respond to any keyboard inputs:

    Code:
    #include<iostream>
    #include<cctype>
    #include<string>
    #include<windows.h>
    using namespace std;
    
    char getch();
    
    int main()
    {
        do{       
              
              cout << "\nEnter something: ";
              
              cout << getch();
              
              cout << "\n\nWould ye' like to try again? (Y/N) ";
              
        }while(toupper(getch())!='N');
        
        return 0;
    }
    
    
    char getch()
    {
         HANDLE hIn;
         INPUT_RECORD InRec; 
         DWORD EventCount, fdwSaveOldMode; 
              
         hIn = GetStdHandle(STD_INPUT_HANDLE); 
         
         GetConsoleMode(hIn, &fdwSaveOldMode);
         
         SetConsoleMode(hIn, ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT);      
                 
         
         for(;;)
         {      
             GetNumberOfConsoleInputEvents(hIn, &EventCount);
             
             if(EventCount)
             {         
                  ReadConsoleInput(hIn, &InRec, 1, NULL);        
             
                  if(InRec.EventType == KEY_EVENT)
                  {          
                       SetConsoleMode(hIn, fdwSaveOldMode);                     
                       return static_cast<signed char>(InRec.Event.KeyEvent.uChar.AsciiChar);  
                  }  
             }             
         }
    }

    Additional info:

    My usage of SetConsoleMode( ) is based on this MSDN excerpt:
    ENABLE_LINE_INPUT
    0x0002 The ReadFile or ReadConsole function returns only when a carriage return character is read. If this mode is disabled, the functions return when one or more characters are available.

    ENABLE_ECHO_INPUT
    0x0004 Characters read by the ReadFile or ReadConsole function are written to the active screen buffer as they are read. This mode can be used only if the ENABLE_LINE_INPUT mode is also enabled.

    Last edited by The Brain; 07-01-2005 at 06:15 PM.
    • "Problem Solving C++, The Object of Programming" -Walter Savitch
    • "Data Structures and Other Objects using C++" -Walter Savitch
    • "Assembly Language for Intel-Based Computers" -Kip Irvine
    • "Programming Windows, 5th edition" -Charles Petzold
    • "Visual C++ MFC Programming by Example" -John E. Swanke
    • "Network Programming Windows" -Jones/Ohlund
    • "Sams Teach Yourself Game Programming in 24 Hours" -Michael Morrison
    • "Mathmatics for 3D Game Programming & Computer Graphics" -Eric Lengyel

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    A couple of things:
    - ReadConsoleInput() doesn't say that NULL is valid for the last parameter.
    - Don't poll for input. It's not nice to eat up the CPU.
    - Don't bother with ENABLE_ECHO_INPUT and ENABLE_LINE_INPUT - they don't affect ReadConsoleInput().
    Code:
    int getch()
    {
        HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
        if (!hIn)
            return -1;
    
        DWORD fdwSaveOldMode;
        if (!GetConsoleMode(hIn, &fdwSaveOldMode) ||
            !SetConsoleMode(hIn, 0))
            return -1;
    
        int c = -1;
    
        while (1)
        {
            if (WaitForSingleObject(hIn, INFINITE) != WAIT_OBJECT_0)
                break;
            
            INPUT_RECORD InRec;
            DWORD numRead;
            if (!ReadConsoleInput(hIn, &InRec, 1, &numRead))
                break;
    
            if ((InRec.EventType == KEY_EVENT) &&
                InRec.Event.KeyEvent.bKeyDown)
            {
                c = InRec.Event.KeyEvent.uChar.AsciiChar;
                break;
            }//if
        }//while
    
        SetConsoleMode(hIn, fdwSaveOldMode);
    
        return c;
    }//getch
    This is still a long ways off from mimicking the MS getch() behavour.

    gg

  3. #3
    Registered User
    Join Date
    Jul 2005
    Posts
    69
    I had a little password input routine that I converted over to getch( ) and getche( ). getche( ) is the same except with character echo to screen. I guess it's similar to what's already posted but then again I guess it should be. It easy to modify by expanding or limiting input around isprint(...); It's been so long since I used Turbo C++ getch( ) that I don't actually remember what key-presses should be responded to.

    Regards,
    Brian

    Code:
    char getch(void)  
    {
    	DWORD dwCharsRead;
    	INPUT_RECORD inRec;
    	HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
    	 
    	while(ReadConsoleInput(hInput, &inRec, 1, &dwCharsRead))  
    		if(inRec.EventType == KEY_EVENT && inRec.Event.KeyEvent.bKeyDown
    			&& isprint(inRec.Event.KeyEvent.uChar.AsciiChar))
    				return(inRec.Event.KeyEvent.uChar.AsciiChar);
    		
    	return('ì'); // dummy return to suppress warning msg.
    }
    Code:
    char getche(void)  
    {  
    	INPUT_RECORD inRec;
    	char buffer[2] = {'\0'};
    	DWORD dwCharsRead, dwCharsWritten;
    	HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);  
    	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);  
    	 
    	while(ReadConsoleInput(hInput, &inRec, 1, &dwCharsRead))  
    		if(inRec.EventType == KEY_EVENT && inRec.Event.KeyEvent.bKeyDown
    			&& isprint(inRec.Event.KeyEvent.uChar.AsciiChar))
    		{
    			buffer[0] = inRec.Event.KeyEvent.uChar.AsciiChar;
    			WriteConsole(hOutput, buffer, 1, &dwCharsWritten, NULL);
    			return(inRec.Event.KeyEvent.uChar.AsciiChar);
    		}
    		
    	return('ì'); // dummy return to suppress warning msg.
    }
    Code:
    #include <windows.h>
    #include <iostream>
    #include <cstdlib>
    
    using namespace std;
    
    /* Password function for Win32 console  
    * reads keystrokes but displays * to mask printable entries  
    * first parameter: a pointer to a char array, buffer to hold password  
    * second parameter: password buffer size, including null terminator  
    * return value: funtion returns 1 if max buffer is reached, else returns 0  
    */  
     
    int Password( char * buffer, int buffSize)  
    {  
    	int count = 0;  
    	INPUT_RECORD inRec;  
    	HANDLE hInput, hOutput;  
    	DWORD dwCharsRead, dwCharsWritten;  
    	 
    	buffSize--;  
    	hInput = GetStdHandle(STD_INPUT_HANDLE);  
    	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);  
    	 
    	while(ReadConsoleInput(hInput, &inRec, 1, &dwCharsRead) && count < buffSize)  
    		if(inRec.EventType == KEY_EVENT && inRec.Event.KeyEvent.bKeyDown == TRUE)  
    			if(isprint(inRec.Event.KeyEvent.uChar.AsciiChar))  
    				buffer[count++] = inRec.Event.KeyEvent.uChar.AsciiChar,  
    				WriteConsole(hOutput, "*", 1, &dwCharsWritten, NULL);  
    			else  
    			if(inRec.Event.KeyEvent.uChar.AsciiChar == '\b' && count > 0)  
    				WriteConsole(hOutput, "\b \b", 3, &dwCharsWritten, NULL),  
    				count--;  
    			else  
    			if(inRec.Event.KeyEvent.uChar.AsciiChar == '\r')  
    				break;  
    	 
    	buffer[count] = '\0';  
    	 
    	if(count == buffSize)  
    	return(1);  
    	else  
    	return(0);  
    }  
    
    int main( int argc, char * argv[] )
    {
    	char buffer[256];
    	
    	cout << endl << endl << "Enter Password: ";
    	Password(buffer, 256);
    	
    	return(0);
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. making it portable.....?
    By ShadeS_07 in forum C Programming
    Replies: 11
    Last Post: 12-24-2008, 09:38 AM
  2. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  3. Pls repair my basketball program
    By death_messiah12 in forum C++ Programming
    Replies: 10
    Last Post: 12-11-2006, 05:15 AM
  4. Pause a C program without getch()
    By swgh in forum C Programming
    Replies: 4
    Last Post: 02-20-2006, 11:24 AM
  5. Clearing input buffer after using getch()
    By milkydoo in forum C++ Programming
    Replies: 3
    Last Post: 07-21-2003, 11:04 PM