2

背景: GUI モードとコンソール モードの両方を実行できる C++ MFC アプリケーションを開発しています。ただし、どちらの場合も、ユーザーはコマンドプロンプトを使用してアプリケーションを実行し、引数を指定する必要があります。アプリケーションを初期化すると、コマンド プロンプトで入力引数の使用がチェックされ、コンソール モードまたは 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同じ文字列の場合。何か案が?

4

2 に答える 2

1

これは、文字列がワイド文字列であるためです (末尾の から推測するWSetWindowTextW、narrow-character を使用した場合のワイド文字列の出力は、std::cout多くの場合、不可解な 16 進数です)。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;
}
于 2013-02-08T08:50:45.637 に答える
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));
}
于 2013-02-27T05:41:54.640 に答える