Как отчистить буфер консоли winapi

Рейтинг: 0Ответов: 1Опубликовано: 14.07.2023

У меня есть простенький класс для работы с консолью, его задача максимально сблизить консоль с обычным графическим интерфейсом, соответственно, мне нужно сделать так, что бы консоль можно было отчисть, максимально быстрым способом (system("cls") вообще не вариант, слишком медленно). У меня есть вариант перезаписать информацию в буфере на тех-же позициях (или отчистить буфер), как это реализовать я не понимаю, я пытался сдвинуть каретку в нулевые координаты и отрисовать фрейм, но он рисовался ниже первого.

Код файла с классом "экрана" (rgbConsole.hpp):

#include <iostream>
#include <windows.h>
#include <sstream>

using namespace std;

string pixel(float r, float g, float b, string str = " "){
    stringstream ss;
    ss << "\033[48;2;" << r << ";" << g <<";" << b <<"m"<< str <<"\033[0;0m";
    return ss.str();
}

class Screen{
    public:

    HANDLE buffer1, buffer2;
    DWORD buffWritten1, buffWritten2;
    int ActiveBuffer = 0;
    Screen(){
        buffer1 = GetStdHandle(STD_OUTPUT_HANDLE);
        buffer2 = CreateConsoleScreenBuffer(GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
    }

    void Write(string s){
        WriteConsole(ActiveBuffer == 0 ? buffer1 : buffer2,
                     s.c_str(),
                     s.size(),
                     ActiveBuffer == 0 ? &buffWritten1 : &buffWritten2,
                     NULL);
    }

    void ShowBuffer(){
        SetCaretPos(0, -12);
    }

    void SwapBuffers(){
        SetConsoleActiveScreenBuffer(ActiveBuffer == 0 ? buffer1 : buffer2);
        SetCaretPos(0, 0);
        ActiveBuffer == 0 ? ActiveBuffer = 1 : ActiveBuffer = 0;
    }

    void quit(){
        CloseHandle(buffer1);
        CloseHandle(buffer2);
    }
};

Код main.cpp:

#include "EXT/rgbConsole.hpp"
using namespace std;

int main(){
    Screen screen;
    
    for(int i = 0; i < 2; i++){
        string frame;
        for(int y = 0; y < 12; y++){
            for(int x = 0; x < 40; x++){
                frame+=pixel(255, x*10, y*10);
            }
            frame+="\n";
        }
        screen.Write(frame);
        screen.ShowBuffer();
        //screen.SwapBuffers();
    }

    screen.quit();
}

Команда SwapBuffers дает результат, но только на один раз.

Результат вывода кода:

введите сюда описание изображения

Если будет активен SwapBuffers, изображение будет одно, но если будет 3 фрейма, произойдет вот это:

введите сюда описание изображения

OS: Windows 11

Консоль: PowerShell (vscode) / Windows Terminal

Компилятор: g++ v7.3.0

Ответы

▲ 0

Вместо SetCaretPos надо использовать SetConsoleCursorPosition, и использовать глобальные координаты. Таким образом если указать координаты (0, 0) можно переписать то, что уже было написано.