Change entire console background color (Win32 C++) - c++

How can I change the entire console's background color? I've tried SetConsoleTextAttribute and it only changes the background color of new text.
I effectively want the entire console to turn red when a serious error arises.
Thanks to everyone who attempts to help.

Try something like:
system("color c2");

I think the FillConsoleOutputAttribute function will do what you need. Set it to the starting coordinate of the console, and set nLength to the number of characters in the console (width * length).
BOOL WINAPI FillConsoleOutputAttribute(
__in HANDLE hConsoleOutput,
__in WORD wAttribute,
__in DWORD nLength,
__in COORD dwWriteCoord,
__out LPDWORD lpNumberOfAttrsWritten
);

I know this is an old question, but how about this code:
#include <windows.h>
#include <iostream>
VOID WINAPI SetConsoleColors(WORD attribs);
int main() {
SetConsoleColors(BACKGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
std::cout << "Hello, world!" << std::endl;
std::cin.get();
return 0;
}
VOID WINAPI SetConsoleColors(WORD attribs) {
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFOEX cbi;
cbi.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
GetConsoleScreenBufferInfoEx(hOutput, &cbi);
cbi.wAttributes = attribs;
SetConsoleScreenBufferInfoEx(hOutput, &cbi);
}
As far as I know this code should work on Windows Vista and later versions. By the way, this code is based on this article (mainly the sources on the article): http://cecilsunkure.blogspot.fi/2011/12/windows-console-game-set-custom-color.html

It can be done and the whole background can be set to desired color with SetConsoleScreenBufferInfoEx. The code below should not mess with the previous console output, especially if it used colors:
#include "Windows.h"
void FlashConsoleBackgroundColor(int cntFlashes, int flashInterval_ms, COLORREF color)
{
CONSOLE_SCREEN_BUFFER_INFOEX sbInfoEx;
sbInfoEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
HANDLE consoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfoEx(consoleOut, &sbInfoEx);
COLORREF storedBG = sbInfoEx.ColorTable[0];
for (int i = 0; i < cntFlashes; ++i)
{
//-- set BG color
Sleep(flashInterval_ms);
sbInfoEx.ColorTable[0] = color;
SetConsoleScreenBufferInfoEx(consoleOut, &sbInfoEx);
//-- restore previous color
Sleep(flashInterval_ms);
sbInfoEx.ColorTable[0] = storedBG;
SetConsoleScreenBufferInfoEx(consoleOut, &sbInfoEx);
}
}
int main()
{
printf("Flashing console BG: RED");
FlashConsoleBackgroundColor(20, 50, RGB(255, 0, 0));
printf("\rFlashing console BG: ORANGE\n");
FlashConsoleBackgroundColor(10, 100, RGB(255, 105, 0));
return 0;
}

HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(out, 0x9 | 0x70);
// text color from 0x1-0x9
// text background color from 0x10-0x90
system("color d1");
/*
Sets the default console foreground and background colors
COLOR [attr]
attr Specifies color attribute of console output
Color attributes are specified by TWO hex digits -- the first
corresponds to the background; the second the foreground. Each digit
can be any of the following values:
0 = Black 8 = Gray
1 = Blue 9 = Light Blue
2 = Green A = Light Green
3 = Aqua B = Light Aqua
4 = Red C = Light Red
5 = Purple D = Light Purple
6 = Yellow E = Light Yellow
7 = White F = Bright White
If no argument is given, this command restores the color to what it was
when CMD.EXE started. This value either comes from the current console
window, the /T command line switch or from the DefaultColor registry
value.
The COLOR command sets ERRORLEVEL to 1 if an attempt is made to execute
the COLOR command with a foreground and background color that are the
same.
/*

This works for me. It changes the background color without messing up the foreground color of text already displayed, by changing each console character cell, one at a time. You will need to get the handle to your console output buffer, which I believe is done with GetStdHandle().
DWORD written = 0;
COORD writeCoord = {0};
WORD attribute;
for (int y = 0; y < consoleBufferLength; y++) // rows
{
for (int x = 0; x < consoleBufferWidth; x++) // columns
{
writeCoord.X = x; writeCoord.Y = y;
ReadConsoleOutputAttribute(consoleOutputHandle, &attribute, 1, writeCoord, &written);
attribute &= 0xFF0F; // zero the background color
attribute |= 12 << 4; // change the background color to red
FillConsoleOutputAttribute(consoleOutputHandle, attribute, 1, writeCoord, &written);
}
}

I have a dirty way here, but gives what you exactly want.
#include <windows.h>
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole,30);
system("CLS");
console

Related

Enabling ANSI Color support in Windows console with custom screen buffer (C++)

I'm trying to enable ANSI color support for created console screen buffer via CreateConsoleScreenBuffer().
hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
DWORD dwMode = 0;
GetConsoleMode(hConsole, &dwMode);
dwMode |= ENABLE_EXTENDED_FLAGS;
SetConsoleMode(hConsole, dwMode);
dwMode = 0;
GetConsoleMode(hConsole, &dwMode);
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hConsole, dwMode);
SetConsoleActiveScreenBuffer(hConsole);
It seems like SetConsoleMode() isn't doing anything, I can write it to buffer as I intended, but if I try to write any ANSI Escape codes, it looks like this
If I'm not in buffer created by CreateConsoleScreenBuffer(), ANSI Escape codes are working as expected.
EDIT: I'm on Windows 10, 19041.388; C++14, MinGW-64 compiler
You could use this:
#include <windows.h>
#include <iostream>
void Color(int color=0x07)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
int main()
{
Color(0x0A/*Black bg green Fg*/);
std::cout << "Hello";
Color();
std::cout << ",";
Color(0xAC/*Green bg red Fg*/);
std::cout << "World";
Color(/*Black bg white Fg*/);
}
For more information about the colors:
Color attributes are specified by TWO hex digits -- the first
corresponds to the background; the second the foreground. Each digit
can be any of the following values:
0 = Black 8 = Gray
1 = Blue 9 = Light Blue
2 = Green A = Light Green
3 = Aqua B = Light Aqua
4 = Red C = Light Red
5 = Purple D = Light Purple
6 = Yellow E = Light Yellow
7 = White F = Bright White
Virtual terminal sequences are control character sequences that can
control cursor movement, color/font mode, and other operations when
written to the output stream. Sequences may also be received on the
input stream in response to an output stream query information
sequence or as an encoding of user input when the appropriate mode is
set.
You can use GetConsoleMode and SetConsoleMode functions to configure
this behavior.
From ENABLE_VIRTUAL_TERMINAL_PROCESSING, we can use WriteFile or WriteConsole to achieve.
Some code:
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hConsole_c = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
SetConsoleActiveScreenBuffer(hConsole_c);
DWORD dwMode = 0;
GetConsoleMode(hConsole_c, &dwMode);
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hConsole_c, dwMode);
const char* str = "\x1b[31mThis text has restored the foreground color only.\r\n";
DWORD len = strlen(str);
DWORD dwBytesWritten = 0;
WriteConsole(hConsole_c, str, len, &dwBytesWritten, NULL);
Debug:

How to read a range of pixels c++

I'm doing a program that reads a range of pixels and if find the red color, do a click with left mouse button, but it is too slow, like if the red dot shows up on the range, it takes 2 seconds or more to click.
This is a representation of the problem:
So if some red dot cross the green line, click with left mouse button. The green line do not exist, I drew it just to make it clearer.
Can someone propose a solution to read this interval in milliseconds?
I think that the problem is to use a for loop to check the pixel colors.
I tried to use the solution proposed in the topic "Get Pixel color fastest way?" but this made the computer very slow and did not work. (I made some adjustments to adapt the solution to my problem). Also, because my problem is much simpler, I think there is a simpler solution than the one in the other topic, which is more complex and did not work for me.
This is my code:
int main()
{
HDC dc = GetDC(NULL);
POINT pt;
int x = 150;
while (1) {
for (int y = 205; y >= 0; y--) {
dc = GetDC(NULL);
COLORREF color = GetPixel(dc, x, y);
// the red color has value = 220
if (color == 220) {
GetCursorPos(&pt);
mouse_event(MOUSEEVENTF_LEFTDOWN, pt.x, pt.y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, pt.x, pt.y, 0, 0);
}
}
}
ReleaseDC(NULL, dc);
}
Should you be getting a new image every time you're checking the pixel color? Off the top of my head maybe GETDC should be before the for loop.
while (1) {
dc = GetDC(NULL);
for (int y = 205; y >= 0; y--) {
COLORREF color = GetPixel(dc, x, y);

WriteConsoleOutputCharacter Drawing extra pixel thick of blank space

Ive been designing a roguelike video game in the console.
My problem is i initially draw the entire map with writeconsoleoutput at once then use writeconsoleoutputcharacter to redraw whats neccessary. But i have found that it draws an extra pixel thick on the right side.
This essentially erases one pixel off the tile on the right side.
Does anyone know a way to make it stop drawing a character and adding a 1 pixel blank space on the right side of the character.
EDIT: ONE WORKAROUND I HAVE FOUND IS TO REDRAW THE LINES THE PLAYER STEPS ON BUT IT ISNT PERFECT ONCE IN A WHILE I CAN NOTICE A FLICKER. Would be preferable to just redraw characters on an individual basis without any pixels attached on the end. or anywhere else.
The Code used to print the character
void printchar(char character, COORD location,short color)
{
const char *pointer = &character;
//short LENGTH = 1;
DWORD dwWritten = 0;
std::vector<WORD> attributes;attributes.clear();;
setAttributesChar(color,attributes);//Pushes back the color
if(attributes.size() == 1)
{ WriteConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE),&attributes[0], attributes.size(), location, &dwWritten);
WriteConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), pointer, attributes.size(), location, &dwWritten);
}
}
void setAttributesChar(short color,std::vector<WORD> &attributes)
{
switch(color)
{
case DEFAULTCOLOR:
attributes.push_back(FOREGROUND_INTENSE_WHITE);return;
case HOVEREDCOLOR:
attributes.push_back(FOREGROUND_GREEN);return;
case RED:
attributes.push_back(FOREGROUND_RED);return;
case GOLD:
attributes.push_back(FOREGROUND_INTENSE_YELLOW);return;
case REDWHITE:
attributes.push_back(COMBINED_REDWHITE);return;
case YELLOWPURPLE:
attributes.push_back(COMBINED_YELLOWPURPLE);return;
case NPCCOLOR:
attributes.push_back(FOREGROUND_INTENSE_CYAN);return;
case PURPLE:
attributes.push_back(FOREGROUND_MAGENTA);return;
case REDPURPLE:
attributes.push_back(COMBINED_REDPURPLE);return;
case BLUE:
attributes.push_back(FOREGROUND_BLUE);return;
case BLUEPURPLE:
attributes.push_back(COMBINED_BLUEPURPLE);return;
case INTENSEGREEN:
attributes.push_back(FOREGROUND_INTENSE_GREEN);return;
case REDGREEN:
attributes.push_back(COMBINED_REDGREEN);return;
case BWHITE:
attributes.push_back(BACKGROUND_WHITE);return;
}
}
EXAMPLE:
BEFORE CHARACTER WALKS OVER ROAD: BEFORE IMAGE
AFTER CHARACTER WALKS OVER ROAD: AFTER IMAGE
EXECUTABLE LINK: EXECUTABLE
I have created a working example that you guys can compile(Assuming u use windows) to see what is occuring. In it i create a console set the size fill the screen with the asci symbol 223. then i use Writeconsoleoutchar to print a green 223 symbol. You can see the extra drawn black pixel line.
#include <windows.h>
#include <cwchar>
#include <vector>
enum COLORS{HOVEREDCOLOR};
void setAttributesChar(short color,std::vector<WORD> &attributes)
{
switch(color)
{
case HOVEREDCOLOR:
attributes.push_back(FOREGROUND_GREEN);return;
}
}
void printchar(char character, COORD location,short color)
{
const char *pointer = &character;
//short LENGTH = 1;
DWORD dwWritten = 0;
std::vector<WORD> attributes;attributes.clear();;
setAttributesChar(color,attributes);//Pushes back the color
if(attributes.size() ==1)
{ WriteConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE),&attributes[0], attributes.size(), location, &dwWritten);
WriteConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), pointer, attributes.size(), location, &dwWritten);
}
}
#define SCREENWIDTH 1550
#define SCREENHEIGHT 850
void SETWINDOWUP(DWORD &SIZE)
{
CONSOLE_SCREEN_BUFFER_INFO info;
MoveWindow(GetConsoleWindow(),0,0,SCREENWIDTH,SCREENHEIGHT,true); //MOVE WINDOW TO 0,0 AND MAKE 1600 BY 880
::SetWindowPos(GetConsoleWindow(), HWND_TOPMOST, 0, 0, 0,0, SWP_DRAWFRAME | SWP_NOREPOSITION | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); //SET WNDOWS POSITION COMPARED TO OTHER WINDOWS IN DRAW ORDER
::SetWindowPos(GetConsoleWindow(),HWND_NOTOPMOST, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hout,&info);
COORD newBuffersize =
{
info.srWindow.Right - info.srWindow.Left + 1,
info.srWindow.Bottom - info.srWindow.Top + 1
};
SetConsoleScreenBufferSize(hout,newBuffersize);
SIZE = info.dwSize.X * info.dwSize.Y;
//EDIT REGULATED FONT SIZE
CONSOLE_FONT_INFOEX cfi;
std::wcscpy(cfi.FaceName, L"Lucida Console"); // Choose your font
cfi.FontFamily = FF_DONTCARE;
cfi.nFont = 0;
cfi.dwFontSize.X = 0;
cfi.dwFontSize.Y = 25; // Height
cfi.FontWeight = FW_BOLD;
cfi.cbSize = sizeof(cfi);
SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), false, &cfi);
}
int main()
{
Sleep(500);DWORD SIZE = 0;SETWINDOWUP(SIZE);
DWORD charswritten;COORD start = {0,0};TCHAR CHARACTER = 223;
FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE),CHARACTER,SIZE,start,&charswritten);
Sleep(500);
printchar(223,{6,5},HOVEREDCOLOR);
Sleep(500);
return 0;
};

How to determine the Console Character over which the Mouse Cursor is on?

I have trouble converting Mouse screen coordinates into the console 2D buffer when the font size is very small. The only method I have found was is this one:
COORD CursorToBuffer()
{
POINT ptCursor;
GetCursorPos(&ptCursor);
ScreenToClient(GetConsoleWindow(), &ptCursor);
/** Now ptCursor has the Mouse Position relative to the console client area. **/
COORD dwBufferPosition;
dwBufferPosition.X = ptCursor.x / dwFontWidth;
dwBufferPosition.Y = ptCursor.y / dwFontHeight;
return dwBufferPosition;
}
When the font is around 12x16, it is accurate. But when the font size is under 10x10, it starts to mess up.
Can I make this more accurate, or is there another method I should use?
Better than calculating the mouse position is getting its real value. Using ReadConsoleInput
Use ReadConsoleInput than you get an INPUT_RECORD with a MOUSE_EVENT_RECORD. It also contains the mouse position.
See sample code in the MSDN
I tested this program and seems to work fine for font sizes smaller than 10x10, it worked even without calling LPtoDPbut I left it in. It calls GetConsoleFontSize to get the font size and it prints it to the output so you can inspect the values as you make the font smaller. Hope it helps.
#include <Windows.h>
#include <sstream>
#include <iostream>
CONSOLE_FONT_INFO fontInfo;
HANDLE hStdout;
HWND hwnd;
HDC hdc;
COORD CursorToBuffer()
{
POINT ptCursor;
GetCursorPos(&ptCursor);
ScreenToClient(hwnd, &ptCursor);
/** Now ptCursor has the Mouse Position relative to the console client area. **/
COORD dwFontSize = GetConsoleFontSize(hStdout, fontInfo.nFont);
POINT dpFontSize = { dwFontSize.X, dwFontSize.Y };
LPtoDP(hdc, &dpFontSize, 0);
COORD dwBufferPosition;
dwBufferPosition.X = ptCursor.x / dpFontSize.x;
dwBufferPosition.Y = ptCursor.y / dpFontSize.y;
std::string fontSize = "fontSize: " + std::to_string(dpFontSize.x) + ' ' + std::to_string(dpFontSize.y) + "\n";
OutputDebugStringA(fontSize.c_str());
return dwBufferPosition;
}
void writeAt(int x, int y, std::string text)
{
COORD position = { x, y };
SetConsoleCursorPosition(hStdout, position);
std::cout << text;
}
int main()
{
hwnd = GetConsoleWindow();
hdc = GetDC(hwnd);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
GetCurrentConsoleFont(hStdout, FALSE, &fontInfo);
while (1) {
COORD cursor = CursorToBuffer();
std::string txt = std::to_string(cursor.X) + " " + std::to_string(cursor.Y) + " \n";
writeAt(1, 1, txt);
}
return 0;
}

Fastest RGB color detection C++

Hi i have used getpixel method, bitblt or what its called (creating bitmap header) and then going though all the values. It is VERY slow. For exapmple if i had to detect something red or specific color it would take very long time. There has gotta be faster way right? I did try using desktop as HWND and then the window i need to find the colors, but desktop was somehow faster.. guesing because it had to look for the window i guess. I get HIGH cpu usage using both methods.
void Get_Color(int x,int y,int w,int h,int &red,int &green,int &blue,int action)
{
HDC hdc, hdcTemp;
RECT rect;
BYTE*bitPointer;
HWND Desktop = GetDesktopWindow();
hdc = GetDC(Desktop);
GetWindowRect(Desktop, &rect);
hdcTemp = CreateCompatibleDC(hdc);
BITMAPINFO bitmap;
bitmap.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmap.bmiHeader.biWidth = w;
bitmap.bmiHeader.biHeight = h;
bitmap.bmiHeader.biPlanes = 1;
bitmap.bmiHeader.biBitCount = 32;
bitmap.bmiHeader.biCompression = BI_RGB;
bitmap.bmiHeader.biSizeImage = 0;
bitmap.bmiHeader.biClrUsed = 0;
bitmap.bmiHeader.biClrImportant = 0;
HBITMAP hBitmap2 = CreateDIBSection(hdcTemp, &bitmap, DIB_RGB_COLORS, (void**)(&bitPointer), NULL, NULL);
HGDIOBJ save = SelectObject(hdcTemp, hBitmap2);
BitBlt(hdcTemp, 0, 0, w, h, hdc, x, y, SRCCOPY);
if(action==1)
{
for(int j=0;j<=w*h*4;j+=4)
{
red = bitPointer[j+2];
green = bitPointer[j+1];
blue = bitPointer[j];
if(red<30 && green>190 && blue>190)
{
break;
}
}
}
else
{
for(int j=0;j<=w*h*4;j+=4)
{
red = bitPointer[j+2];
green = bitPointer[j+1];
blue = bitPointer[j];
break;
}
}
///RELEASE
DeleteObject( SelectObject(hdcTemp, save) );
DeleteDC(hdcTemp);
DeleteDC(hdc);
ReleaseDC(NULL,hdc);
ReleaseDC(NULL,hdcTemp);
}
You may try to break your search. First search in the red channel and, when this succeed look for blue and green values:
for (int j=0; j<=w*h*4; j+=4){
red = bitPointer[j+2];
if (red<30) {
green = bitPointer[j+1];
blue = bitPointer[j];
if (green>190 && blue>190) {
do_something;
}
}
}
You can also try to accelerate via pointer arithmetic (but a good compiler will easily optimize the former):
for (BYTE *pRed=bitPointer+2; pRed<=bitPointer+w*h*4; pRed+=4){
if (pRed<30) {
green = pRed[-1];
blue = pRed[-2];
if (green>190 && blue>190) {
do_something;
}
}
}
If this is not sufficient, you may think about using threads to break the search into separate parallels smaller searches.
I suggest you create a table of RGB values from the bitmap. This would only need to be performed once.
struct RGB
{
unsigned int red;
unsigned int green;
unsigned int blue;
};
RGB rgb_pixels[MAX_ROWS][MAX_COLUMNS];
// ...
for (unsigned int row = 0; row < MAX_ROWS; ++row)
{
for (unsigned int column = 0; column < MAX_COLUMNS; ++column)
{
unsigned red = get_red_value(row, column);
unsigned green = get_green_value(row, column);
unsigned blue = get_blue_value(row, column);
RGB pixel;
pixel.red = red;
pixel.green = green;
pixel.blue = blue;
rgb_pixels[row][column] = pixel;
}
}
Whenever your program needs RGB info from the bitmap, index the array (rgb_pixels).
Accessing the RGB pixel array will be much faster than searching the bitmap and converting, for each pixel you are interested in.
Basically every time you call your method, it is creating an entirely new bitmap and copying it again. You could speed up your program the most by keeping the array of colors between calls to Get_Color(). You could put it in a class or a global variable. Thomas Matthews has a good idea for that. Once that's fixed, Jean-Baptiste Yunès has some good advice to look into.