SetConsoleScreenBufferInfoEx color palette behavior broken #606

Open
opened 2026-01-30 21:56:44 +00:00 by claunia · 0 comments
Owner

Originally created by @PhMajerus on GitHub (Mar 27, 2019).

19H1 has many improvements concerning console colors, but introduced a new bug. (@zadjii-msft is gonna hate me, sorry)
Testing on 19H1 build 18362.1 and comparing with 1809 build 17763.402.

The console was designed to work like a CGA text screen, with modifiable palette like on VGA.
Whenever the palette is changed, the characters already on screen are displayed using the updated palette on its next refresh cycle,
This was how it used to work until Win10 1809...
The new console code doesn't refresh all displayed cells when SetConsoleScreenBufferInfoEx is called.
This is a breaking compatibility change in 19H1, and an undesirable one as some apps might take advantage of the ability to change the palette without having to redraw the whole text screen to change displayed colors. (like how VGA games used colors cycling).

See the following sample code, it outputs text in color # 7 over a background of color # 0.
Since both lines it outputs are using the same colors indexes, they should be shown in the same color, changing the palette applies to the whole screen, including any existing output.

On 19H1, the console screen isn't updated with the new colors until the user either goes into console settings and clicks OK, or tries to resize the window even just a bit, or even just minimizes and restores the window, forcing a repaint.
This is clearly a bug, as minimizing and restoring the window would not change the colors if it was a new intended behavior.

int main()
{
	HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

	CONSOLE_SCREEN_BUFFER_INFOEX csbiex;
	ZeroMemory(&csbiex, sizeof(CONSOLE_SCREEN_BUFFER_INFOEX));
	csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
	GetConsoleScreenBufferInfoEx(hStdOut, &csbiex);
	// Make sure we're using color#0 as background and #7 as foreground
	csbiex.wAttributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;

	// Set blue colors scheme.
	csbiex.ColorTable[0] = RGB(128, 0, 0);
	csbiex.ColorTable[7] = RGB(255, 0, 0);
	SetConsoleScreenBufferInfoEx(hStdOut, &csbiex);
	LPCTSTR pszRedString = TEXT("Bright red on dark red\r\n");
	WriteConsole(hStdOut, pszRedString, _tcslen(pszRedString), NULL, NULL);

	// Set red colors scheme.
	csbiex.ColorTable[0] = RGB(0, 0, 128);
	csbiex.ColorTable[7] = RGB(0, 0, 255);
	SetConsoleScreenBufferInfoEx(hStdOut, &csbiex);
	// At this point, the "Bright red on dark red", as well as all background,
	// for the whole screen should have been turned to blue.
	LPCTSTR pszBlueString = TEXT("Bright blue on dark blue\r\n");
	WriteConsole(hStdOut, pszBlueString, _tcslen(pszBlueString), NULL, NULL);

	getchar();
	return 0;
}

Screen on 1809 and below :
1809 and below

Same on 19H1 (18362.1) :
19H1 bug

Originally created by @PhMajerus on GitHub (Mar 27, 2019). 19H1 has many improvements concerning console colors, but introduced a new bug. (@zadjii-msft is gonna hate me, sorry) Testing on 19H1 build 18362.1 and comparing with 1809 build 17763.402. The console was designed to work like a CGA text screen, with modifiable palette like on VGA. Whenever the palette is changed, the characters already on screen are displayed using the updated palette on its next refresh cycle, This was how it used to work until Win10 1809... The new console code doesn't refresh all displayed cells when SetConsoleScreenBufferInfoEx is called. This is a breaking compatibility change in 19H1, and an undesirable one as some apps might take advantage of the ability to change the palette without having to redraw the whole text screen to change displayed colors. (like how VGA games used colors cycling). See the following sample code, it outputs text in color # 7 over a background of color # 0. Since both lines it outputs are using the same colors indexes, they should be shown in the same color, changing the palette applies to the whole screen, including any existing output. On 19H1, the console screen isn't updated with the new colors until the user either goes into console settings and clicks OK, or tries to resize the window even just a bit, or even just minimizes and restores the window, forcing a repaint. This is clearly a bug, as minimizing and restoring the window would not change the colors if it was a new intended behavior. <pre> int main() { HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFOEX csbiex; ZeroMemory(&csbiex, sizeof(CONSOLE_SCREEN_BUFFER_INFOEX)); csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); GetConsoleScreenBufferInfoEx(hStdOut, &csbiex); // Make sure we're using color#0 as background and #7 as foreground csbiex.wAttributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; // Set blue colors scheme. csbiex.ColorTable[0] = RGB(128, 0, 0); csbiex.ColorTable[7] = RGB(255, 0, 0); SetConsoleScreenBufferInfoEx(hStdOut, &csbiex); LPCTSTR pszRedString = TEXT("Bright red on dark red\r\n"); WriteConsole(hStdOut, pszRedString, _tcslen(pszRedString), NULL, NULL); // Set red colors scheme. csbiex.ColorTable[0] = RGB(0, 0, 128); csbiex.ColorTable[7] = RGB(0, 0, 255); SetConsoleScreenBufferInfoEx(hStdOut, &csbiex); // At this point, the "Bright red on dark red", as well as all background, // for the whole screen should have been turned to blue. LPCTSTR pszBlueString = TEXT("Bright blue on dark blue\r\n"); WriteConsole(hStdOut, pszBlueString, _tcslen(pszBlueString), NULL, NULL); getchar(); return 0; } </pre> Screen on 1809 and below : ![1809 and below](https://user-images.githubusercontent.com/25664275/55102802-82855180-50c7-11e9-94a7-8971f7468415.png) Same on 19H1 (18362.1) : ![19H1 bug](https://user-images.githubusercontent.com/25664275/55102916-bd878500-50c7-11e9-9bbd-d260b9aaba7d.png)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#606