Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting line input from a AllocConsole C++

A team member added the following code to our GUI Ogre project to add a console (so that we are able to see cout as we are debugging...

We are now running way behind time, and we need text interaction with the game, I was going to make a console, but it is plausibly a big time hole... So I thought hey! Why not use the console he attached!! unfortunatly, I was inable to type into it when I attempted, thus I wouldn't be able to send a command to the console :\

Is there any way to enable writing into the console (atm the way he's done it if you hit any key (as such as 'a') nothing goes into the console, therefore I can't wait for enter and then phase the string typed into the win32 console)

Here's his code (I also added the link encase somone has a rough idea, but they want to read about it again, I don't know the exact guide he followed, but it was very simular)

void showWin32Console()
{
    static const WORD MAX_CONSOLE_LINES = 1000;
    int hConHandle;
    long lStdHandle;
    CONSOLE_SCREEN_BUFFER_INFO coninfo;
    FILE *fp;

    // allocate a console for this app
    AllocConsole();

    // set the screen buffer to be big enough to let us scroll text
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
    coninfo.dwSize.Y = MAX_CONSOLE_LINES;
    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

    // redirect unbuffered STDOUT to the console
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "w" );
    *stdout = *fp;
    setvbuf( stdout, NULL, _IONBF, 0 );

    // redirect unbuffered STDIN to the console
    lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "r" );
    *stdin = *fp;
    setvbuf( stdin, NULL, _IONBF, 0 );

    // redirect unbuffered STDERR to the console
    lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "w" );
    *stderr = *fp;
    setvbuf( stderr, NULL, _IONBF, 0 );

    // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
    // point to console as well
    std::ios::sync_with_stdio();
}
like image 438
Michael Crook Avatar asked Oct 25 '12 17:10

Michael Crook


1 Answers

AllocConsole() just gives you a new console, it doesn't change existing stdin/stdout - so the handles you get back from GetStdHandle will still be their former values. Instead you have to open the special devices "CONIN$"/"CONOUT$". Turns out that reassigning stdin/stdout to this new console is actually fairly simple, using freopen:

BOOL f = AllocConsole();
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);

...and presto, all further access to standard input or output will now go to your new console.

(This doesn't change what the Win32's view of your standard input/output handles are, by the way, so if there happens to be other code in the process that calls GetStdHandle(STD_INPUT_HANDLE) etc instead of using the CRT's stdio, those will still return the original values that are not related to your new console. If you need to change those too, then you may need to play around with opening CONIN$/CONOUT$ manually and using SetStdHandle to fix up those.)

like image 128
BrendanMcK Avatar answered Nov 01 '22 13:11

BrendanMcK