This month I will discuss a article that appeared in the Windows Developer's Journal, December 1997. It's written by Andrew Tucker and provides and interesting tool for debuging code.
Many programmers don't know that a Win32 console application can call all the same functions (CreateWindow(), MessageBox(), etc.) as a GUI Win32 application. Conversely, a GUI Win32 application can create a console window and read and write to it – a handy feature if you ever need a line-oriented debugging window. This article shows how to add a console window to your GUI application on the fly, and redirect standard I/O to use that window.
One of the common misconceptions surrounding Win32 programming is that you must decide early in the design process whether your application will be a console or GUI application. In reality, console applications can create windows and have a message loop just like a GUI application (see "Adding Graphics to Console Applications" by Michael Covington, Visual Developer, June/July 1997). Alternatively, graphical applications can create and use a console. Although Win32 provides functions for communicating with a console, they are a little clumsy to use and require parameters that are unnecessary for simple text I/O. This article shows how to use standard C/C++ I/O with consoles, and how to work around specific problems in the Visual C++ I/O library.
void RedirectIOToConsole() { 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 ios::sync_with_stdio(); }