How to Create One line In C++ a Colour

November 26, 2010 at 23:46:29
Specs: Windows 7
Ok well i'm currently making a C++ program and i would like to know how to make a sort of menu kinda thing with one line in the M-DOS C++ Program like Grey or something

A Bit like Zork how it had a Grey Line at the Top


See More: How to Create One line In C++ a Colour

Report •


#1
November 27, 2010 at 00:53:40
Also note this is a texted based program no SDL or Opengl just yet

Report •

#2
November 27, 2010 at 03:56:10
If your only compiling for windows you could use the console API function SetConsoleTextAttribute to change the colo[u]r and then write the text.

Edit:

Another possibility would be FillConsoleOutputAttribute after writing the text.


Report •

#3
November 27, 2010 at 05:05:35
Sorry i'm quiet a noob at C++ and i'm still learning could you give me a code that would set a line in a M-DOS application made in C++

Report •

Related Solutions

#4
November 27, 2010 at 05:40:11
ms-dos != console window.

In windows the character mode windows are called console windows.

If you want ms-dos someone else will have to help because
I don't have much dev experience with it.

For windows console application (windows 2000 and above):

//only tested on xp with dev-cpp

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


int main()
{
    //set up a new console window
    FreeConsole();
    AllocConsole();
    
    //Get the console output handle
    HANDLE hConsoleOutput;
    hConsoleOutput = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hConsoleOutput == INVALID_HANDLE_VALUE)
    {
        std::cerr << "Failed to get the console handle, sys errorcode: " << GetLastError() << std::endl;
        return 1;
    }

    //retrieve the console info    
    CONSOLE_SCREEN_BUFFER_INFO sbiConsoleInfo;
    if (!GetConsoleScreenBufferInfo(hConsoleOutput, &sbiConsoleInfo) )
    {
        std::cerr << "Failed to get the console info, sys errorcode: " << GetLastError() << std::endl;
        return 1;
    }
    
    //change the top line
    DWORD dwWritten = 0;
    COORD dwWriteCoord;
    dwWriteCoord.X = 0;
    dwWriteCoord.Y = 0;
    if (!FillConsoleOutputAttribute(hConsoleOutput, BACKGROUND_RED | FOREGROUND_BLUE, sbiConsoleInfo.dwSize.X,  dwWriteCoord, &dwWritten))
    {
        std::cerr << "Failed to change colour, sys errorcode: " << GetLastError() << std::endl;
        return 1;
    }                                                    
    
    //hit enter to exit
    std::cin.ignore();
    return 0;
}


Report •

#5
November 27, 2010 at 05:40:28

Report •

#6
November 27, 2010 at 06:06:51
This is all very confusing i just want one simple line that can be coloured and i am able place text on that line.

Report •

#7
November 27, 2010 at 06:18:59
That's the windows api, powerful, confusing and frustrating all at the same time...


I don't know of an easier way to change a whole line, like I said in #2 you could also set the attribute and then output your text(i.e even std::cout will output in the selected attributes).

Another possibility would be to create a function to do all the work and just pass it position/colour/coordinates.....


Maybe someone else has a better idea.




Report •

#8
November 27, 2010 at 12:57:43
I'll probably get a skewer in the eye for posting this, but if you can find an old compiler capable of dos apps, then you can use console functions; for example with BC 4.5

#include <stdio.h>
#include <conio.h>
#include <string.h>

#define BGC  1 /* blue  */
#define FGC 15 /* white */

void menu(int x, int bgc, int fgc) {

	gotoxy((80 - strlen(" option 1 ")) / 2, 12);
	textbackground(x == 12 ? bgc : fgc);
	textcolor(x == 12 ? fgc : bgc); cprintf(" option 1 ");

	gotoxy((80 - strlen(" option 2 ")) / 2, 13);
	textbackground(x == 13 ? bgc : fgc);
	textcolor(x == 13 ? fgc : bgc); cprintf(" option 2 ");

	gotoxy((80 - strlen(" option 3 ")) / 2, 14);
	textbackground(x == 14 ? bgc : fgc);
	textcolor(x == 14 ? fgc : bgc); cprintf(" option 3 ");
}

int main(void) {

	int ch, ch2, cx = 12;

	_setcursortype(_NOCURSOR);
	menu(cx, BGC, FGC);

	do {
		ch = getch();
		switch(ch) {
			case 0 : ch2 = getch(); /* 72 up; 80 down */
						switch(ch2) {
							case 72 : if(cx <= 12) { cx = 14; } else { cx--; }
										 break;
							case 80 : if(cx >= 14) { cx = 12; } else { cx++; }
										 break;
						}

						menu(cx, BGC, FGC);
						break;

			case 13 : /* cx = menu target */
						 break;
		}
	} while(ch != 'q');

	_setcursortype(_NORMALCURSOR);
	return 0;
}

HTH


Report •

#9
November 27, 2010 at 20:25:44
Here is a very quick example that wrapping up the API into
simplified functions.

They could be set up however they will best serve, it
doesn't need to ,or indeed probably shouldn't,
be set up exactly how I did it.


Edit: I should also say that there are probably
perfectly good libraries around to do exactly this.

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

bool GotoCell(int,int);
bool ChangeColour(unsigned short, unsigned short);
bool ColourLine(unsigned short, unsigned short, unsigned short);



int main()
{
    //set up a new console window
    FreeConsole();
    AllocConsole();
    

    ColourLine(14, 5, 2);
    ChangeColour(14,5);
    GotoCell(0,2);
    std::cout << "No propper bounds checking - returns false if there is an error";
    GotoCell(0,5);
    std::cout << "press enter to exit";
    
    
    std::cin.ignore();
    return 0;
}



bool GotoCell(int xpos, int ypos)
{
    //Get the console output handle
    HANDLE hConsoleOutput;
    hConsoleOutput = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hConsoleOutput == INVALID_HANDLE_VALUE)
    {
        return false;
    }
    
    //set the cursor position
    COORD coCellCoord;
    coCellCoord.X = xpos;
    coCellCoord.Y = ypos;
    if (!SetConsoleCursorPosition(hConsoleOutput, coCellCoord))
    {
        return false;
    }
    return true;
}

bool ChangeColour(unsigned short FGC, unsigned short BGC)
{
    //only 16 colours
    if (FGC > 15 || BGC > 15)
    {
        return false;
    }

    //Get the console output handle
    HANDLE hConsoleOutput;
    hConsoleOutput = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hConsoleOutput == INVALID_HANDLE_VALUE)
    {
        return false;
    }

    //change the colours
    if (!SetConsoleTextAttribute(hConsoleOutput, ((BGC & 0x0F) << 4) + (FGC & 0x0F)))
    {
        return false;
    }
    return true;
}


bool ColourLine(unsigned short FGC, unsigned short BGC, unsigned short ypos)
{
    //only 16 colours
    if (FGC > 15 || BGC > 15)
    {
        return false;
    }

    //Get the console output handle
    HANDLE hConsoleOutput;
    hConsoleOutput = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hConsoleOutput == INVALID_HANDLE_VALUE)
    {
        return false;
    }

    //retrieve the console info    
    CONSOLE_SCREEN_BUFFER_INFO sbiConsoleInfo;
    if (!GetConsoleScreenBufferInfo(hConsoleOutput, &sbiConsoleInfo) )
    {
        return false;
    }

    //change the top line
    DWORD dwWritten = 0;
    COORD coWriteCoord;
    coWriteCoord.X = 0;
    coWriteCoord.Y = ypos;
    if (!FillConsoleOutputAttribute(hConsoleOutput, ((BGC & 0x0F) << 4) + (FGC & 0x0F), sbiConsoleInfo.dwSize.X,  coWriteCoord, &dwWritten))
    {
        return false;
    }
    return true;
}



Report •

#10
November 28, 2010 at 12:55:55
Thanks that should work for me :P

Report •


Ask Question