在C ++控制台应用程序中打印字符串资源(字符串表)

时间:2013-02-08 08:46:54

标签: c++ visual-c++

背景 我正在开发一个可以运行GUI和控制台模式的C ++ MFC应用程序。但是在这两个时候用户需要使用带有一些参数的命令提示符运行应用程序当Init启动应用程序时,它会在命令提示符下检查use输入参数,并决定在控制台模式或GUI模式下运行。此应用程序需要使用多种语言。所以我使用字符串表来存储显示文本。

所以在这里我使用这个函数将现有的命令提示符附加到应用程序,以便在应用程序作为控制台模式运行时显示状态。

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;
}

然后像这样将状态打印到控制台。

this->EnableConsolePrinting();  
cout << CMsg(IDS_STRING_ERROR_MESSAGE); 

在GUI模式下,我使用此方法在标签中显示文本。

lblError.SetWindowTextW(CMsg(IDS_STRING_ERROR_MESSAGE));

问题:两种方法编译运行正常。但GUI模式显示正确的字符串和控制台打印一些意义较少的代码像这样。 00C2D210表示相同的字符串。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

这是因为字符串是宽字符串(从W中的尾随SetWindowTextW猜测,并且在使用窄字符std::cout时输出宽字符串通常是一个神秘的十六进制数字)。使用wcout将宽字符串输出到控制台。

std::wcout << CMsg(IDS_STRING_ERROR_MESSAGE);

标准输出流可能无法直接打印CString,在这种情况下,您可能需要为其添加输出运算符重载:

std::ostream& operator<<(std::ostream& os, const CString& str)
{
    auto length = str.GetLength();
    os << str.GetBuffer(length + 1);
    str.ReleaseBuffer();

    return os;
}

答案 1 :(得分:0)

这里我通过几天的测试来回答我的问题。这适用于Windows环境。

#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));
}