我正在尝试打印到我用 winapi 创建的新屏幕缓冲区,但它会转到旧缓冲区并且不会显示在屏幕上,是否可能,重定向 cout
到使用 winapi 创建的新屏幕缓冲区?
#include <iostream>
#include <Windows.h>
int main() {
HANDLE stdBuf, nBuf;
DWORD numberOfChars;
stdBuf = GetStdHandle(STD_OUTPUT_HANDLE);
nBuf = CreateConsoleScreenBuffer(GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
SetConsoleActiveScreenBuffer(nBuf);
SetStdHandle(STD_OUTPUT_HANDLE, nBuf);
// THIS SHOWING UP ON THE SCREEN
WriteConsole(nBuf, "SECOND BUFFER", 13, &numberOfChars, NULL);
// THIS IS GOING TO THE FIRST BUFFER
std::cout << "SECOND BUFFER with cout" << std::endl;
Sleep(3000);
SetConsoleActiveScreenBuffer(stdBuf);
CloseHandle(nBuf);
int a = 0;
std::cin >> a;
return 0;
}
最佳答案
是的,这是可能的。不,这不一定完全微不足道。
基本问题相当简单:存在与命名文件对话的现有流缓冲区,但(可能)没有与控制台对话的现有流缓冲区。为了让它工作,你需要一个与控制台对话的人。这是一个相当简单的起点:
class outbuf : public std::streambuf {
HANDLE h;
public:
outbuf(HANDLE h) : h(h) {}
protected:
virtual int_type overflow(int_type c) override {
if (c != EOF) {
DWORD written;
WriteConsole(h, &c, 1, &written, nullptr);
}
return c;
}
virtual std::streamsize xsputn(char_type const *s, std::streamsize count) override {
DWORD written;
WriteConsole(h, s, count, &written, nullptr);
return written;
}
};
[注意:这有点不完整——控制台输出正常,但如果(例如)你复制或分配它,可能会发生不好的事情——就像大多数流缓冲区一样,你可能不应该能够复制或分配它。]
一旦你有了一个将输出写入控制台的流缓冲区,将它连接到 cout
就非常简单了:
console_stream_buffer buff(nBuf);
std::cout.rdbuf(buff);
std:cout << "bleh"; // should go to the console `nBuf`.
这是一个使用它的快速演示:
int main() {
HANDLE h = CreateConsoleScreenBuffer(GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
HANDLE original = GetStdHandle(STD_OUTPUT_HANDLE);
// Create our stream buffer object
outbuf ob(h);
// write to the original buffer
std::cout << "First console";
// Set cout to go to the second buffer
std::cout.rdbuf(&ob);
// write to it
std::cout << "Second console";
// display the second buffer
SetConsoleActiveScreenBuffer(h);
// show the second buffer for a few seconds:
Sleep(5000);
// restore the original buffer
SetConsoleActiveScreenBuffer(original);
}
当然,如果您愿意,您可以轻松地编写一个流缓冲区,为自己分配一个控制台屏幕缓冲区。我暂时将其分开,但根据您的使用方式,将它们组合起来可能更有意义(并且可能包含一个调用 SetConsoleActiveScreenBuffer
的 activate
成员以及)。不过,这些都与您原来的问题无关,所以我暂时不提了。
关于c++ - 将 cout 重定向到使用 winapi 创建的新缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39110882/