コンソールの表示と出力

概要

アウトプット枠ではなく一旦コンソールを表示してそこにいろいろと表示したくなることもあることでしょう。

コンソール起動

PICTURE

  • C++側のソース

    DisplayConsole.dllとしてコンパイル
    #include <windows.h>
    #include <string>
    #include <iostream>
    #include <fcntl.h> // _O_TEXT
    #include <io.h> // _open_osfhandle
    
    #include "HmCppInvoke.h"
    
    using namespace Hidemaru;
    using namespace std;
    
    
    void SetAllocConsoleStream()
    {
        // プロセスにコンソールを割り当てる(ref:A2-1)
        AllocConsole();
    
        // 現在の std::cout, std::wcout が接続されたストリーム(=FILE*) stream_std_out を開く
        FILE* stream_std_out = []()
        {
            // internal-step-1:
            // 標準デバイス(=STD_OUTPUT_HANDLE=標準出力を示すフラグ)の"Windowsにおけるハンドル"(=wh_std_out)を取得
            auto wh_std_out = GetStdHandle(STD_OUTPUT_HANDLE); // (ref:A2-2)
    
            // internal-step-2:
            // 既存の標準出力のWindowsにおけるハンドル(=wh_std_out)を
            // CRT(C run-time)のファイル・ディスクリプター(=fd_std_out)として開く
            //   note: このファイル・ディスクリプターをRAII的に閉じる必要はありません (ref:A2-2-a)
            auto fd_std_out = _open_osfhandle((intptr_t)wh_std_out, _O_TEXT); // (ref:A2-3)
    
            // internal-step-3: 
            // 直前に開かれたCRTのファイル・ディスクリプターをCRTのストリーム(FILE*)として開く
            return _fdopen(fd_std_out, "w"); // (ref:A2-4)
        }();
    
        // 現在の std::cerr, std::wcerr が接続された stream を開く
        FILE* stream_std_error = []()
        {
            // ↑の cout/wcout と同様
            auto wh_std_error = GetStdHandle(STD_ERROR_HANDLE);
            auto fd_std_error = _open_osfhandle((intptr_t)wh_std_error, _O_TEXT);
            return _fdopen(fd_std_error, "w");
        }();
    
        // 現在の std::cin, std::wcin が接続された stream を開く
        FILE* stream_std_in = []()
        {
            // ↑↑の cout/wcout と同様
            auto wh_std_in = GetStdHandle(STD_INPUT_HANDLE);
            auto fd_std_in = _open_osfhandle((intptr_t)wh_std_in, _O_TEXT);
            return _fdopen(fd_std_in, "r");
        }();
    
        // C++ の標準ストリーム系(iostream系なやつら)を C の標準ストリーム系(cstdio系的なやつら)と同期する
        std::ios::sync_with_stdio(true); // (ref:A2-5)
    
    
        // 現在のCRTストリームに接続されたCRTハンドルを閉じつつ、新たにCRTストリームへCRTハンドルを接続する
        freopen_s(&stream_std_out, "CONOUT$", "w", stdout); // (ref:A2-6)
        freopen_s(&stream_std_error, "CONOUT$", "w", stderr);
        freopen_s(&stream_std_in, "CONIN$", "r", stdin);
    }
    
    
    extern "C" __declspec(dllexport) THmNumber test() {
        Hm.funcDllExport();
    
    	//コンソールを作成
    	FreeConsole();
    	AllocConsole();
    
        SetAllocConsoleStream();
    
        try {
            wcout << L"310" << endl;
            printf("310");
        }
        catch (exception& e) {
            // エラー内容をchar → wstring へ
            auto wide_what = Text::Encoding::cp932_to_utf16( e.what() );
            Hm.OutputPane.output(wide_what + L"\r\n");
        }
    
    
        return 1;
    }
    
  • 秀丸マクロ側のソース

    test.mac
    // DisplayConsole.dllとしてコンパイルした
    #dll = loaddll(currentmacrodirectory + @"\DisplayConsole.dll");
     
    // 途中でマクロの文法や型の致命的エラーが発生した場合でもdllを解放する。
    if (version >= 898) { eval "keepdll #dll, 0"; }
     
    #r = dllfuncw(#dll, "test");
     
    freedll(#dll);