Hide Blinking Cursor? Menu Selection and Formatting

I've been working with loops and getch() to create interactive menus in the console, and have been able to embellish them with formatting after making them functional and ensuring that invalid selections do not occur. However, is there a way to hide, or somehow minimize the impact of the blinking cursor that remains wherever the code was working last? Here's a simple example...

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
86
87
#ifndef BASIC_H_INCLUDED
#define BASIC_H_INCLUDED
#endif // BASIC_H_INCLUDED

#include <iostream>
#include<windows.h>
#include<time.h>
#include<conio.h>

using namespace std;

//library with basic helpful functions

void Color(int color)
{   //simplify color changing
    HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hCon,color);
}

void clear()
{   //system("cls") alternative
    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)
{   //cordinates of top/left corner and width, height used to create border
     //no text within the border is disturbed
    //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;
    //lefthand and righthand 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;
    }
    //bottom left corner
    cursorJump(x,y+height,false);
    cout<<bl_corner;
    //top and 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;
    }
    //bottom right corner
    cursorJump(x+width,y+height,false);
    cout<<br_corner;
    //top right coner
    cursorJump(x+width,y,false);
    cout<<tr_corner;
}

menu.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
#ifndef MENU_H_INCLUDED
#define MENU_H_INCLUDED
#endif // MENU_H_INCLUDED

int betMenu(int cash,int minBet)
{
    clear();
    int choice=0,state=0;
    int check;
    //handle border and formatting
    border(8,7,64,3);
    cursorJump(8,9,false);
    cout<<(char)204;
    for (int i=0; i<64; i++)
        cout<<(char)205;
    cout<<(char)185;
    for (int i=21; i<61; i+=13)
    {
        cursorJump(i,9,false);
        cout<<(char)203;
        cursorJump(i,10,false);
        cout<<(char)186;
        cursorJump(i,11,false);
        cout<<(char)202;
    }

    //used to determine which options are valid
    check=((cash>=minBet*20) ? 5 : (cash>=minBet*15) ? 4 :
           (cash>=minBet*10) ? 3 : (cash>=minBet*10) ? 2 : 1);
    while (choice==0)
    {
        cursorJump(19,8,false);
        if (state==0)
            Color(225);
        cout<<"Use \33/\32 and ENTER to place bet from your $"<<cash;


            for (int i=1;i<6;i++)
            {
            cursorJump(13*i,10,false);
            if (check<i)
                Color(8);
            else if (state==i)
                Color(225);
            else
                Color(7);
            cout<<"$"<<((i==1) ? minBet : (i==2) ? minBet*5 : (i==3) ? minBet*10 :
                        (i==4) ? minBet*15 : minBet*20);
            Color(7);
            }
        char c=getch();
        //move right on right arrow, if not in initial
        //state or at highest valid selection
        if (c==77 && state<check && state!=0)
            state++;
        //move left on left arrow, if not
        //at lowest valid selection or initial state
        if (c==75 && state>1)
            state--;
        //move to lowest valid selection on
        //left arrow when in initial state
        if (c==75 && state==0)
            state=1;
        //move to highest valid selection on
        //right arrow when in initial state
        if (c==77 && state==0)
            state=check;
        //choose selected option on ENTER
        //when not in initial state
        if (c==13 && state!=0)
            choice=state;
    }//only quit loop upon valid selection
        choice=((choice==1) ? minBet : (choice==2) ? minBet*5 :
                (choice==3) ? minBet*10 : (choice==4) ? minBet*15 : minBet*20);
        return choice;
}

main.cpp
1
2
3
4
5
6
7
8
9
10
11
#include "basic.h"
#include "menu.h"

int main()
{
    int cash=2500, minBet=50;
    int bet=betMenu(cash,minBet);
    clear();
    cout<<"You chose to bet $"<<bet<<" from your $"<<cash<<".";

}

The values of cash and minBet can be altered, and the logic is included to prevent selection of bets exceeding the cash available, but that cursor is annoying and complicates attempts to further embellish formatting. It looks even worse when the blinking cursor is located on a spot where text already exists, causing the colors to invert.
Last edited on
The functions are GetConsoleCursorInfo() and SetConsoleCursorInfo()
Interesting. After doing a bit of research, I came up with this function:
1
2
3
4
5
6
7
8
9
void SetCursorSize(const int iSize = 0)
{
   HANDLE cxHandle;
   cxHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cci;
    cci.dwSize = iSize;
    cci.bVisible = true;
    SetConsoleCursorInfo(cxHandle, &cci );
}//End SetCursorSize 

It will allow me to change the size of the cursor from 1-99 using commands such as SetCursorSize(99);, but won't get rid of cursor visibility.

However, a bit of further research and I came up with the following:
1
2
3
4
5
6
7
8
9
10
void ShowConsoleCursor(bool showFlag)
{
    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);

    CONSOLE_CURSOR_INFO     cursorInfo;

    GetConsoleCursorInfo(out, &cursorInfo);
    cursorInfo.bVisible = showFlag; // set the cursor visibility
    SetConsoleCursorInfo(out, &cursorInfo);
}

Now, a simple command such as ShowConsoleCursor(false); can turn on/off visibility of the cursor at will. Thanks for getting me on the right track, Duoas. These functions look handy enough to add to my basic header.
Last edited on
Don't forget to leave the console the way it was when your program found it, so make sure to get information like the cursor size and visibility at the beginning of your program and restore it before terminating.

Enjoy!
Interestingly, the console seems to revert to it's default each time, although it could be OS or compiler specific. It seems like handy advice that can't hurt, and will be more likely to work cross-platform, though.
Topic archived. No new replies allowed.