Reputation: 24766
Background: I'm developing a C++ MFC application that can run both GUI and Console modes. But at both time user need to run application using command prompt with some argument. When Init the application it checks the use input arguments on command prompt and decide to run in console mode or GUI mode. This application need to work with multiple language. So I'm using string table to store display texts.
So here I use this function to attached existing command prompt to application to show status when the application run as console mode.
BOOL CMyclass::EnableConsolePrinting(){
BOOL GotConsoleAttach = FALSE;
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
int osfh = _open_osfhandle((intptr_t) GetStdHandle(STD_OUTPUT_HANDLE), 8);
if ((HANDLE)osfh != INVALID_HANDLE_VALUE)
{
*stdout = *_tfdopen(osfh, _T("a"));
GotConsoleAttach = TRUE;
}
}
return GotConsoleAttach;
}
And then prints the status to console like this.
this->EnableConsolePrinting();
cout << CMsg(IDS_STRING_ERROR_MESSAGE);
In GUI mode I use this method to show text in a label.
lblError.SetWindowTextW(CMsg(IDS_STRING_ERROR_MESSAGE));
Question: Both method compile and run fine. But GUI mode shows correct string and Console prints some meaning less code like this. 00C2D210
for same string. Any idea?
Upvotes: 2
Views: 1067
Reputation: 24766
Here I'm answering my question by doing some testing few days. This is for windows environment.
#define GetCMsg(x) CString(MAKEINTRESOURCE(x))
void myClass::redirectIOToConsole()
{
#define MAX_CONSOLE_LINES 500
int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// If you need to allocate a new console for this app
//AllocConsole();
//Attach existing console for this application
AttachConsole(ATTACH_PARENT_PROCESS);
// 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();
}
void myClass::writeToConsole(wstring result){
const HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD numWritten = 0;
WriteConsoleW(stdOut, result.c_str(), result.size(), &numWritten, NULL);
cout.flush();
}
void myClass::myFoo(){
//attache current console to application
this->redirectIOToConsole();
//write Unicode strings to current console
this->writeToConsole(GetCMsg(IDS_STRING_ERROR_MESSAGE));
}
Upvotes: 0
Reputation: 409176
It's because the strings are wide-character strings (guessing from the trailing W
in SetWindowTextW
, and the output of a wide-character string when using narrow-character std::cout
is often a cryptic hexademinal number). Use wcout
to output wide-character strings to the console.
std::wcout << CMsg(IDS_STRING_ERROR_MESSAGE);
It might be that the standard output stream might not be able to print CString
directly, in which case you will probably have to add an output operator overload for it:
std::ostream& operator<<(std::ostream& os, const CString& str)
{
auto length = str.GetLength();
os << str.GetBuffer(length + 1);
str.ReleaseBuffer();
return os;
}
Upvotes: 1