更改整个控制台背景颜色(Win32 C++)

11

如何更改控制台的整体背景颜色? 我已经尝试了 SetConsoleTextAttribute ,但它只会更改新文本的背景颜色。

实际上,我希望在出现严重错误时整个控制台都变成红色。

感谢每个尝试帮助的人。


听起来在C#中这是一个简单的工作,但在C++中就不一样了 :| 快速搜索后没有找到任何东西。也许只需将文本背景设置为红色,并打印一个由大部分空格字符组成的整个字符数组,其中包含您的文本,也在红色背景上?我认为这可能符合解决方法的条件。 - Xeo
在Windows命令语言中,这很简单:color 4f,就这样。 :-) - Cheers and hth. - Alf
@Alf:这意味着这个可以工作:system("cmd /c \"color 4F\"") - David R Tribble
@Loadmaster 这很好用。我知道这通常不被推荐,也不太可移植等等,但是我认为这是我目前仅有的选择。除非我能够找出如何在C++中执行COLOR所做的同样的事情(我相信这是可能的)。 - Smurf64
7个回答

6
我认为FillConsoleOutputAttribute函数可以满足您的需求。将其设置为控制台的起始坐标,将nLength设置为控制台中字符的数量(width * length)。
BOOL WINAPI FillConsoleOutputAttribute(
  __in   HANDLE hConsoleOutput,
  __in   WORD wAttribute,
  __in   DWORD nLength,
  __in   COORD dwWriteCoord,
  __out  LPDWORD lpNumberOfAttrsWritten
);

1
非常接近,但已包含字符的单元格仍保留先前的背景颜色。 - Smurf64
我的Win32/Console可能有点生疏了。你可以尝试使用WriteConsoleOutputAttribute吗?那可能是你要找的东西。 - Adam Maras

6
尝试做类似于以下的事情:
system("color c2");

1
+1 简单而有效,即使使用 system 调用速度较慢。 - greatwolf
我最终选择了这个。虽然我更喜欢API函数,但这个非常简单且运行良好。 - Smurf64
不起作用!它只改变了文本颜色和文本背景颜色,而非整个控制台的颜色。 - Jai

3

我知道这是一个老问题,但是这段代码怎么样:

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

据我所知,这段代码应该可以在Windows Vista及更高版本上运行。顺便说一下,这段代码基于这篇文章(主要是文章中的源代码):http://cecilsunkure.blogspot.fi/2011/12/windows-console-game-set-custom-color.html

由于某些原因,每次颜色更改时这个解决方案会导致我的控制台窗口缩小。 - madladzen

1
可以使用SetConsoleScreenBufferInfoEx来实现,并且可以将整个背景设置为所需颜色。下面的代码不应该影响先前的控制台输出,特别是如果它使用了颜色:
 #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;
    }

1
这个答案与@MaGetzUb上面的答案有何不同?它们都展示了如何使用_GetConsoleScreenBufferInfoEx_和_SetConsoleScreenBufferInfoEx_,只是你的答案似乎过于复杂了。 - Kyle Shanafelt
实际上,尽管看起来相似,但我的代码在功能上有很大不同。@MaGetzUb的代码会更改所有具有与最后一行打印的字符相同属性的字符的前景色和背景色。如果您之前没有使用过SetConsoleTextAttribute,则整个背景都会更改。但是,在此之前添加:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x96); printf("Some previous console output\n");...它就会失败。我的示例仅更改一个颜色,即无论之前打印了什么,都会更改背景的颜色。此外,作为奖励,您可以将其设置为自定义RGB。 - Killzone Kid

1
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.
/*

0

这对我很有效。它通过逐个更改每个控制台字符单元,而不会弄乱已显示的文本的前景色,从而更改背景颜色。您需要获取控制台输出缓冲区的句柄,我相信可以使用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);
    }
}

0

我这里有一个不太优雅的方法,但可以得到你想要的结果。

  #include <windows.h>
  hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  SetConsoleTextAttribute(hConsole,30);
  system("CLS");

控制台


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接