Buffered console output

I've been working with menu creation and positional movements within the console window, and while I've been able to disable the annoying ever blinking cursor, I notice that alterations in on screen output are still subject to various flashes and anomalies. However, I understand there is a way to buffer output to have the content pre-prepared before output, if you will, to avoid this issue. Does anyone have any info they can add on this topic?

Here is a simple example of what I am referring to. The code will move a box around the screen using the numpad (have numlock on), and +/- and PgUp/PgDn can be used to alter the box's width and height. In the course of moving the object around, or changing it's size the movement is not as seamless as one would expect.
basic.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#ifndef BASIC_H_INCLUDED
#define BASIC_H_INCLUDED
#endif // BASIC_H_INCLUDED

#include<iostream>//required for cout
#include<windows.h>//required for rand
#include<time.h>//required for time
#include<conio.h>
using namespace std;
  void clear()
{
    COORD topLeft={0,0};
    HANDLE console=GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO screen;
    DWORD written;

    GetConsoleScreenBufferInfo(console,&screen);
    FillConsoleOutputCharacterA(console,' ',screen.dwSize.X * screen.dwSize.Y, topLeft, &written);
    FillConsoleOutputAttribute(console, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
                               screen.dwSize.X * screen.dwSize.Y, topLeft,&written);
    SetConsoleCursorPosition(console,topLeft);
}

void cursorJump(short x,short y, bool clearLine)
{
    //move to desired position
    COORD cursor={x,y};
    HANDLE console=GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(console,cursor);
    //clear remaining line when desired
    if (clearLine==true)
    {
        for (int i=x;i<80;i++)
        cout<<" ";
        //return to desired position
        cursorJump(x,y,false);
    }
}

void border(int x,int y,int width,int height)
{   //function to create border, with x and y
    //as coordinates of the top/left corner
    //text inside border remains unaltered

    //increment values to make them inclusive
    width++,height++;
    char v_side=186,h_side=205;
    char tl_corner=201,tr_corner=187;
    char br_corner=188,bl_corner=200;

    //top left corner
    cursorJump(x,y,false);cout<<tl_corner;
    //bottom left corner
    cursorJump(x,y+height,false);cout<<bl_corner;
    //top right coner
    cursorJump(x+width,y,false);cout<<tr_corner;
    //bottom right corner
    cursorJump(x+width,y+height,false);cout<<br_corner;

    //top/bottom sides
    for (int i=x+1;i<width+x;i++)
    {
        cursorJump(i,y+height,false);
        cout<<h_side;
        cursorJump(i,y,false);
        cout<<h_side;
    }
    //left/right sides
    for (int i=y+1;i<height+y;i++)
    {
        cursorJump(x,i,false);
        cout<<v_side;
        cursorJump(x+width,i,false);
        cout<<v_side;
    }
}

void showCursor(bool showFlag)
{   //enable/disable cursor visibility
    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cursorInfo;
    GetConsoleCursorInfo(out, &cursorInfo);
    cursorInfo.bVisible = showFlag; // set the cursor visibility
    SetConsoleCursorInfo(out, &cursorInfo);
}

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "basic.h"

int main()
{
    int x=38,y=10;//default positional values
    int w=1,h=1;//minimum width and height

    showCursor(false);//disable cursor visibility

    while (true)
    {
        //set up border with width/height
        //of w and h at x and y position
        //x and y are top left corner
        border(x,y,w,h);
        char c=getch();//get user input

        //User interface:
        //Numpad 2/8 Used for Up and Down
        if (c==56 && y>0)
            y--;
        else if (c==50 && y<18)
            y++;
        //numpad 4/6 Used for Left and Right
        else if (c==52 && x>0)
            x--;
        else if (c==54 && x<68)
            x++;
        //+/- Buttons Used for Increased/Decreased Width
        else if (c==43 && w<10)
            w++;
        else if (c==45 && w>1)
            w--;
        //PgUp/PgDn Used for Increased/Decreased Height
        else if (c==81 && h<5)
            h++;
        else if (c==73 && h>1)
            h--;
        //numpad diagonals applied
        else if (c==55 && y>0 && x>0)
        {
            x--;
            y--;
        }
        else if (c==57 && y>0 && x<68)
        {
            x++;
            y--;
        }
        else if (c==49 && x>0 && y<18)
        {
            x--;
            y++;
        }
        else if (c==51 && x<68 && y<18)
        {
            x++;
            y++;
        }
        //Enter Key to quit
        else if (c==13)
        break;
        //clear screen before drawing new position/size on repeat of loop
        clear();
    }
}
Last edited on
Topic archived. No new replies allowed.