简体   繁体   中英

SetTextColor not changing command line text color

Since BGI is obsolete, and a lot of its source code seems to be missing from the original website, I've been meaning to design my own color engine that will affect lines individually. So far, the 16 colors that "SetConsoleTextAttribute ()" from windows.h can accept have been doing fine, but I've been meaning to use more colors (by using RGB instead of 0xbf) to upgrade the look of it and color my own ASCII art.

"SetTextColor ()" seems to be the route I want to go. I've set up a testing function to see if it works. Here's the snippet of code with the setup.

HDC hType;    // Handle DC, save some work to reduce repetition
int initColor ()    // Initializes engine
{
    hType = GetDC (GetConsoleWindow ());

    printf ("String     Hexadecimal\n");
    testcolorR (RGB(255, 0, 0));    // Red
    testcolorR (RGB(0, 255, 0));    // Green
    testcolorR (RGB(0, 0, 255));    // Blue

    getch ();    // Pause to see results
    return 0;    // Exit success
}

// Take in RGB
void colortextR (COLORREF rgbcolor)
{
    SetTextColor (hType, rgbcolor);
}

// Test RGB colors
int testcolorR (COLORREF color)
{
    colortextR (color);
    printf ("Hello      %#x\n", color);
    return 0;
}

However, on the command line, the color did not change and remained as the default light-gray, but this is the result.

  1. String Hexadecimal
  2. Hello 0xff
  3. Hello 0xff00
  4. Hello 0xff0000

Which means that the RGB color is being passed, but something else is causing this problem. I suspect the culprit is the GetConsoleWindow () function.

SetTextColor is a GUI function; it will not have the effect you want in a standard Windows console.


If your application will only be run on Windows 10 build 14392 or later, or on (most) non-Windows platforms such as Linux, then you can generally use virtual terminal sequences . Please note that even on supported versions of Windows, VT functionality must be explicitly enabled:

// error handling omitted for brevity; see GetLastError
HANDLE hOut = GetStdHandle( STD_OUTPUT_HANDLE );
if( hOut == INVALID_HANDLE_VALUE ) { return; }

DWORD dwMode = 0;
if( !GetConsoleMode( hOut, &dwMode ) ) { return; }
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if( !SetConsoleMode( hOut, dwMode ) ) { return; }

std::cout << "\x1b[91mRed\n"
          << "\x1b[92mGreen\n"
          << "\x1b[94mBlue\n"
          << "\x1b[38;5;221mArbitrary RGB color\n"
          << "\x1b[0mReset colors\n";

If your application needs to run on older versions of Windows, and the standard 16-color palette is sufficient, then something similar to the following will work (see SetConsoleTextAttribute and console screen buffer text attributes ):

// error handling omitted for brevity; see GetLastError
HANDLE hOut = GetStdHandle( STD_OUTPUT_HANDLE );
if( hOut == INVALID_HANDLE_VALUE ) { return; }

// save current buffer information
CONSOLE_SCREEN_BUFFER_INFO sbInfo{ sizeof CONSOLE_SCREEN_BUFFER_INFO };
GetConsoleScreenBufferInfo( hOut, &sbInfo );

SetConsoleTextAttribute( hOut, FOREGROUND_RED | FOREGROUND_INTENSITY );
std::cout << "Red\n";

SetConsoleTextAttribute( hOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY );
std::cout << "Green\n";

SetConsoleTextAttribute( hOut, FOREGROUND_BLUE | FOREGROUND_INTENSITY );
std::cout << "Blue\n";

SetConsoleTextAttribute( hOut, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN );
std::cout << "Light Gray\n";

SetConsoleTextAttribute( hOut, sbInfo.wAttributes );
std::cout << "Reset colors\n";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM