I have a win32 application that need to open a console like the games when tilde is pressed. I tought that the best solution is to use the CreateWindow function. Is this right?
The solutions here won't work because newer versions of the Windows SDK define the FILE structure by:
#ifndef _FILE_DEFINED
#define _FILE_DEFINED
typedef struct _iobuf
{
void* _Placeholder;
} FILE;
#endif
When trying to overwrite the stdin/out FILE structures with the = operator, only one pointer will be copied. To copy the whole FILE struct, you have to define the FILE structure before your windows.h include:
#ifndef _FILE_DEFINED
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
#define _FILE_DEFINED
#endif
#include <Windows.h>
If this is somehow not possible for you, you can still define your own FILE structure as FILE_COMPLETE and use this codesnippet:
#include <Windows.h>
#include <io.h>
#include <fcntl.h>
AllocConsole();
SetConsoleTitleA("ConsoleTitle");
typedef struct { char* _ptr; int _cnt; char* _base; int _flag; int _file; int _charbuf; int _bufsiz; char* _tmpfname; } FILE_COMPLETE;
*(FILE_COMPLETE*)stdout = *(FILE_COMPLETE*)_fdopen(_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT), "w");
*(FILE_COMPLETE*)stderr = *(FILE_COMPLETE*)_fdopen(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w");
*(FILE_COMPLETE*)stdin = *(FILE_COMPLETE*)_fdopen(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "r");
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
This is some pretty old code, haven't even really looked over it. Hopefully it's what you need. If you just need a very simple one you can also just make a call to AllocConsole();
void DevConsole::Create(){
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
int consoleHandleR, consoleHandleW ;
long stdioHandle;
FILE *fptr;
AllocConsole();
std::wstring strW = L"Dev Console";
SetConsoleTitle( strW.c_str() );
EnableMenuItem(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE , MF_GRAYED);
DrawMenuBar(GetConsoleWindow());
GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo );
stdioHandle = (long)GetStdHandle( STD_INPUT_HANDLE );
consoleHandleR = _open_osfhandle( stdioHandle, _O_TEXT );
fptr = _fdopen( consoleHandleR, "r" );
*stdin = *fptr;
setvbuf( stdin, NULL, _IONBF, 0 );
stdioHandle = (long) GetStdHandle( STD_OUTPUT_HANDLE );
consoleHandleW = _open_osfhandle( stdioHandle, _O_TEXT );
fptr = _fdopen( consoleHandleW, "w" );
*stdout = *fptr;
setvbuf( stdout, NULL, _IONBF, 0 );
stdioHandle = (long)GetStdHandle( STD_ERROR_HANDLE );
*stderr = *fptr;
setvbuf( stderr, NULL, _IONBF, 0 );
}
It's often tempting to use a console window in your app (using AllocConsole
), but it is definitely NOT a standard reusable Windows control. It has a lot of special behaviors and features which make it unique from a typical window.
For this reason, I would agree with your instinct, against using a true 'Console' window. Make your own window with a text editor in it, as you would develop any other UI component like a HUD.
Whether you should use CreateWindow
is hard to say: how are you doing the rest of your GUI? DirectX? GDI? Some toolkit? Are you using other standard windows controls?
I found this little tutorial / code samples useful. http://www.halcyon.com/~ast/dload/guicon.htm
It creates a console and redirects STD_IN and STD_OUT to the console. So you can easily use std::cin and std::cout etc streams.