下面的课程将让您了解您需要做什么。在构建时,CConsole 尝试使用 AllocConsole 为进程创建一个新控制台。
如果 AllocConsole 失败,则不会发生任何变化——控制台已经存在,并且该类假定 C-Runtime 句柄已经在其他地方设置。
如果 AllocConsole 成功,则保存当前与 stdout 和 stdin 关联的对象,然后将这些对象替换为为新控制台创建的对象。现在 C-Runtime 输出函数(如 printf)将输出到新的控制台。cout 和 cin 也将使用新的控制台。
RemoveMenu 调用将阻止用户关闭控制台窗口,从而终止进程。没有必要超出此功能。
当 CConsole 被销毁(并且 AllocConsole 成功)时,stdout 和 stdin 被恢复,然后通过调用 FreeConsole 关闭控制台。
当您希望控制台在创建它的函数之外持续存在时,我发现这个类很不方便——您需要获取一个新的 CConsole 并跟踪它的指针,直到您通过删除关闭它。但它的实施列出了您在自己的项目中需要采取的步骤。我从未尝试过使用 dll 进行此操作,但我看不出有任何原因会造成问题。
控制台.h:
#pragma once
#include <stdio.h>
class CConsole {
FILE m_OldStdin, m_OldStdout;
bool m_OwnConsole;
public:
CConsole();
~CConsole();
};
控制台.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();
}
}
享受!