I'm trying to print to the new screen buffer that i've create with winapi but it's going to the old buffer and doesn't show up on the screen, is it possible, redirecting cout to the new screen buffer that created by using 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;
}
Yes, it's possible. No, it's not necessarily entirely trivial.
The basic problem is fairly simple: there are existing stream buffers to talk to a named file, but (probably) not an existing one to talk to a console. To get this to work, you need one that talks to a console. Here's a fairly simple starting point:
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;
}
};
[Note: this is somewhat incomplete--it does the Console output fine, but if (for example) you copy or assign it, bad things will probably happen--like most stream buffers, you probably shouldn't be able to copy or assign it.]
Once you have a stream buffer that writes its output to a console, connecting it up to cout is pretty trivial:
console_stream_buffer buff(nBuf);
std::cout.rdbuf(buff);
std:cout << "bleh"; // should go to the console `nBuf`.
Here's a quick demo using it:
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);
}
You could, of course, easily write a stream buffer that allocates a console screen buffer for itself, if you wanted to. I left that separate for now, but depending on how you're using things, it may easily make more sense to combine them (and probably include an activate member that calls SetConsoleActiveScreenBuffer as well). None of that is really relevant to your original question though, so I'll leave it for now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With