gpt4 book ai didi

c++ - 将 cout 重定向到使用 winapi 创建的新缓冲区

转载 作者:太空狗 更新时间:2023-10-29 20:54:26 24 4
gpt4 key购买 nike

我正在尝试打印到我用 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);
}

当然,如果您愿意,您可以轻松地编写一个流缓冲区,为自己分配一个控制台屏幕缓冲区。我暂时将其分开,但根据您的使用方式,将它们组合起来可能更有意义(并且可能包含一个调用 SetConsoleActiveScreenBufferactivate 成员以及)。不过,这些都与您原来的问题无关,所以我暂时不提了。

关于c++ - 将 cout 重定向到使用 winapi 创建的新缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39110882/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com