Skip to main content
GameDev.net gamedev.net
🔒 Locked

separate console window

Started by Khaos Dragon May 19, 2003 at 10:06 PM 17 replies 1.6k views
Original Post
Khaos Dragon
Khaos Dragon
I am making an open gl game (the point being I don''t have access to a console right now) and I would like to be able to make a separate console window for debugging purposes through which i can output data. Is there an easy way for me to be able to make that window and then write data to it with something like cout??
antareus
antareus

  
//DebugConsole.h

#ifndef DEBUGCONSOLE_H
#define DEBUGCONSOLE_H

/// Creates a debug console that lasts the duration of the DebugConsole object

/// lifetime, and syncs stdin/stdout/stderr and the C++ streams to print there.

class DebugConsole
{
public:
DebugConsole();
~DebugConsole();

private:
bool m_exists;
};

#endif

//DebugConsole.cpp

#include "DebugConsole.h"

#include <iostream>
#include <fcntl.h>
#include <io.h>
#include <windows.h>

using namespace std;

DebugConsole::DebugConsole()
{
m_exists = ::AllocConsole() != 0;
if(! m_exists)
::MessageBox(0, TEXT("Couldn't create debug console!"), TEXT("Error"), MB_ICONERROR | MB_OK);

//sync stdin, stdout, stderr fds up with the new console

//original source: http://www.halcyon.com/ast/dload/guicon.htm

//changes: removed all warnings by changing types and casting


// set the screen buffer to be big enough to let us scroll text

CONSOLE_SCREEN_BUFFER_INFO coninfo;
::GetConsoleScreenBufferInfo(::GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = 500;
::SetConsoleScreenBufferSize(::GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

// redirect unbuffered STDOUT to the console

intptr_t pStdHandle = reinterpret_cast<intptr_t>(::GetStdHandle(STD_OUTPUT_HANDLE));
int hConHandle = _open_osfhandle(pStdHandle, _O_TEXT);
FILE* pFile = _fdopen( hConHandle, "w" );
*stdout = *pFile;
setvbuf( stdout, NULL, _IONBF, 0 );

// redirect unbuffered STDIN to the console

pStdHandle = reinterpret_cast<intptr_t>(::GetStdHandle(STD_INPUT_HANDLE));
hConHandle = _open_osfhandle(pStdHandle, _O_TEXT);
pFile = _fdopen( hConHandle, "r" );
*stdin = *pFile;
setvbuf( stdin, NULL, _IONBF, 0 );

// redirect unbuffered STDERR to the console

pStdHandle = reinterpret_cast<intptr_t>(::GetStdHandle(STD_ERROR_HANDLE));
hConHandle = _open_osfhandle(pStdHandle, _O_TEXT);
pFile = _fdopen( hConHandle, "w" );
*stderr = *pFile;
setvbuf( stderr, NULL, _IONBF, 0 );

// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog

// point to console as well

ios::sync_with_stdio();
}

DebugConsole::~DebugConsole()
{
if(m_exists)
{
::FreeConsole();
m_exists = false;
}
}


[edited by - antareus on May 19, 2003 11:37:05 PM]
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
Khaos Dragon
Khaos Dragon
Hmmm it makes the console window fine but cout or stdout doesn''t work at all.

It may be because my compiler didn''t recognize the intptr_t type at all but through a quick google search i saw intptr_t used as a typedef for long so I substituted long. It compiles fine but now I get no output to the console window made.
masonium
masonium
I may be way off, but...
I'm assuming you're using MSVC 6 and the OpenGL app is a win32 application. If that's true, then there is a linker(?) setting that you can use so that your program will have a console even though it enters through WinMain. Go to Project and click Settings... Go to Link and in the text field you have to type '/subsystem:console' and '/entry:WinMainCRTStartup' without the quotes. That should work, I think. When you do this, you will have both a console window and whatever window your app creates.


Check out my raytracer at http://simp-raytracer.sourceforge.net. Download it at http://www.sourceforge.net/projects/simp-raytracer.


EDITED

[edited by - masonium on May 19, 2003 12:30:08 AM]
Khaos Dragon
Khaos Dragon

You probably only missed like a slight detail or something but yeah that doesn''t do anything at all just by adding those 2 compiler options.
Khaos Dragon
Khaos Dragon
no one knows how to do this at all?
Jan Wassenberg
Jan Wassenberg
Patience, dude

Try mainCRTStartup, it should work (I''ve done it before).

Alternative to antareus''s lowIO method (simpler, safer):

AllocConsole();
freopen("CONIN$", "w", stdin);
freopen("CONOUT$", "w", stdout);

You might have to use the DLL CRT.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
kdogg
kdogg
You can make openGL programs with a console window. Just rename winmain to main and tell your compiler you''re making a console program instead of a win32 program. You also might want to write your debug data to a log file instead of outputting it to the screen.
Khaos Dragon
Khaos Dragon
quote:
Original post by kdogg
You can make openGL programs with a console window. Just rename winmain to main and tell your compiler you''re making a console program instead of a win32 program. You also might want to write your debug data to a log file instead of outputting it to the screen.


Yes I realize that, but for some reason I could not output to the window even though it created one (the same thing happened with antareus''s code). The AllocConsole and freeopen functions however worked beautifully, I can now use the standard i/o stream to output and input data on my secondary console window which is real nice.

I would however, prefer to use the iostream cin and cout objects instead, is there a way I can do this? I tried a
"ios::sync_with_stdio();" command, but it did nothing.

By the way I appreciate everyone''s help so thanks!

antareus
antareus
Strange, I''m not sure why it''d work okay here and not there.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
mfawcett
mfawcett
This is the version I've been using forever. You can extend it if you want to also bind cerr and cin to the new console.


    
const int MAX_CONSOLE_LINES = 250;

void RedirectIOToConsole(void)
{
int hConHandle;
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

hConHandle = _open_osfhandle((intptr_t)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
fp = _fdopen(hConHandle, "w");
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
}


I give this code to my students and haven't had a case where it didn't work on their machine, so hopefully that's the case for you guys.

ant's code and mine are very similar. I've found this exact code at many many locations online.

Here's one link to it -> http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_10037191.html

and here's another -> http://home.earthlink.net/~barnold2002/Acgnj/Csig0204.htm


Looks like it was originally posted in Windows Developer's Journal.


[edited by - mfawcett on May 24, 2003 7:12:54 PM]
--Michael Fawcett
uNiQue0815
uNiQue0815
while we''re at it...

is there a way to use main(), without a console to appear under windows ?
antareus
antareus
quote:
Original post by uNiQue0815
while we''re at it...

is there a way to use main(), without a console to appear under windows ?


Yes, you make a Win32 project (not a console project) and use WinMain as your entry point.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
Jan Wassenberg
Jan Wassenberg
Maybe he wants a portable application?

Answer: set subsystem to Win32, and entry point to mainCRTStartup.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
uNiQue0815
uNiQue0815
thx... that''s what i''m looking for... (the portable app. one)
Skizz
Skizz
I once wrote an application that would sit in the system tray and log all messages sent to it. Then, in any application that I was developing, I could send a message to the logging application. The advantage here is that the output isn''t lost whenever the program exited.
Implementing your message output as a macro will make it easier to port to other environments.

Skizz
daerid
daerid
quote:
Original post by Skizz
I once wrote an application that would sit in the system tray and log all messages sent to it. Then, in any application that I was developing, I could send a message to the logging application. The advantage here is that the output isn''t lost whenever the program exited.
Implementing your message output as a macro will make it easier to port to other environments.

Skizz


That''s actually a brilliant idea, BUT, couldn''t you just have your application log the stuff by itself? Why add the extra window?
daerid@gmail.com
uNiQue0815
uNiQue0815
i already thought about this, too...

what would be the problem... one would only open this window when developing and debugging, and not in release... so there wouldn''t be an extra window.

if doing it with a macro, one could also define the macro empty, for release compilation, so sending messages doesn''t cost cpu cycles and you got no effort to switch between debug & release...
antareus
antareus
I''d let my debug window be shown in release mode for applications. Bind it something like control-tilde (mm, Quake console).
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.