次のクラスでは、何をする必要があるかについてのアイデアが得られます。構築時に、CConsole は AllocConsole を使用してプロセス用の新しいコンソールを作成しようとします。
AllocConsole が失敗した場合、何も変更されません。コンソールは既に存在し、クラスは C ランタイム ハンドルが別の場所に既に設定されていると想定します。
AllocConsole が成功すると、現在 stdout と stdin に関連付けられているオブジェクトが保存され、新しいコンソール用に作成されたオブジェクトに置き換えられます。これで、C ランタイム出力関数 (printf など) が新しいコンソールに出力されます。cout と cin も新しいコンソールを使用します。
RemoveMenu 呼び出しは、ユーザーがコンソール ウィンドウを閉じるのを防ぎ、プロセスを終了します。この機能以外は必要ありません。
CConsole が破棄されると (そして AllocConsole が成功すると)、stdout と stdin が復元され、FreeConsole への呼び出しでコンソールが閉じられます。
コンソールを作成した機能を超えてコンソールを存続させたい場合、このクラスは不便だと思います。新しい CConsole を取得し、削除で閉じるまでそのポインタを追跡する必要があります。ただし、その実装では、独自のプロジェクトで実行する必要がある手順が示されています。dll でこれを試したことはありませんが、これが問題になる理由はわかりません。
Console.h:
#pragma once
#include <stdio.h>
class CConsole {
FILE m_OldStdin, m_OldStdout;
bool m_OwnConsole;
public:
CConsole();
~CConsole();
};
Console.cpp:
#include <windows.h>
#include <conio.h>
#include <FCNTL.H>
#include <io.h>
#include "Console.h"
static BOOL WINAPI MyConsoleCtrlHandler(DWORD dwCtrlEvent) { return dwCtrlEvent == CTRL_C_EVENT;}
CConsole::CConsole() : m_OwnConsole(false) {
if(!AllocConsole()) return;
SetConsoleCtrlHandler(MyConsoleCtrlHandler, TRUE);
RemoveMenu(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE, MF_BYCOMMAND);
const int in = _open_osfhandle(INT_PTR(GetStdHandle(STD_INPUT_HANDLE)), _O_TEXT);
const int out = _open_osfhandle(INT_PTR(GetStdHandle(STD_OUTPUT_HANDLE)), _O_TEXT);
m_OldStdin = *stdin;
m_OldStdout = *stdout;
*stdin = *_fdopen(in, "r");
*stdout = *_fdopen(out, "w");
m_OwnConsole = true;
}
CConsole::~CConsole() {
if(m_OwnConsole) {
fclose(stdout);
fclose(stdin);
*stdout = m_OldStdout;
*stdin = m_OldStdin;
SetConsoleCtrlHandler(MyConsoleCtrlHandler, FALSE);
FreeConsole();
}
}
楽しみ!