【问题标题】:SetTextColor not changing command line text colorSetTextColor 不改变命令行文本颜色
【发布时间】:2018-12-12 01:40:38
【问题描述】:

由于 BGI 已经过时,而且它的很多源代码似乎从原始网站中丢失,我一直打算设计我自己的颜色引擎来单独影响线条。到目前为止,windows.h 中的“SetConsoleTextAttribute ()”可以接受的 16 种颜色都做得很好,但我一直打算使用更多颜色(通过使用 RGB 而不是 0xbf)来升级它的外观并为我的颜色着色自己的ASCII艺术。

“SetTextColor()”似乎是我想走的路线。我已经设置了一个测试功能,看看它是否有效。这是带有设置的代码的 sn-p。

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;
}

但是,在命令行中,颜色并没有改变,仍然是默认的浅灰色,但这就是结果。

  1. 十六进制字符串
  2. 你好 0xff
  3. 你好 0xff00
  4. 你好 0xff0000

这意味着正在传递 RGB 颜色,但其他原因导致了此问题。我怀疑罪魁祸首是 GetConsoleWindow () 函数。

【问题讨论】:

  • 或者控制台窗口可能不像你想象的那样工作
  • SetTextColor() 不是处理这个问题的方法。您必须使用SetConsoleTextAttribute(),因此您最多只能使用 16 种颜色 - 但是 - 您可以使用 SetConsoleScreenBufferInfoEx() 将这 16 种颜色设置为您想要的任何 RGB 值。请参阅this answerRGB Specific Console Text Color
  • 所以不幸的是,除了修改 16 种颜色之外,我没有其他解决方法。如果有其他方法,我仍然愿意接受任何其他可能有效的解决方案。
  • 编写自己的控制台(或使用第三方的)?
  • 我想我之前尝试过这样做,但实际上最终只使用了 16 种颜色。 cmd 似乎不支持您想要的

标签: c++ windows winapi


【解决方案1】:

SetTextColor是一个GUI函数;它不会在标准 Windows 控制台中产生您想要的效果。


如果您的应用程序只能在 Windows 10 build 14392 或更高版本上运行,或者在(大多数)非 Windows 平台(如 Linux)上运行,那么您通常可以使用virtual terminal sequences。请注意,即使在受支持的 Windows 版本上,也必须明确启用 VT 功能:

// 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";

如果您的应用程序需要在旧版本的 Windows 上运行,并且标准的 16 色调色板就足够了,那么类似于以下内容将起作用(请参阅 SetConsoleTextAttributeconsole 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";

【讨论】:

  • 谢谢。我想我在其文档中没有看到它是用于 GUI 的。
  • @jam:在documentation 的顶部有一个面包屑导航栏,反映了文档的层次结构。 SetTextColorWindows GDI 的一部分。
  • 由于 ENABLE_VIRTUAL_TERMINAL_PROCESSING 标志对我来说不存在,我阅读并发现它的值是 0x0004。仅供查看此答案的其他人注意。
  • @Jamesthe1 如果未定义 ENABLE_VIRTUAL_TERMINAL_PROCESSING,您很可能使用的是较旧的 SDK。显然,该标志在构建 10586 之前或前后的某个时间点(悄悄地)添加到控制台子系统,但直到下一个版本:1607 或构建 14393 才添加到 SDK 标头中。我无法亲自验证这一点我目前可以直接从 10.0.10240.0 跳转到 10.0.15063.0 的标头。
  • @pandorafalters 我猜我使用的是旧版 SDK,因为我从 MinGW 获得了文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多