[FAQ - pytania (które dostaje via
e-mail/IRC/jabber/etc, oraz na które natrafiam na forach) + moje odpowiedzi]
Topic z forum 4programmers.net,
pytanie o dowolne kolory w konsoli Windowsa oraz o polskie znaki. Moja odpowiedź poniżej:
Hey,
[...]
Zgadza się! A konkretniej, jest 16 kolorów z palety którą można samemu zdefiniować (tj. można samemu zdefiniować na Vista/2008/7/etc; nie testowałem na XP, ale wg. MSDN funkcje do redefiniowania palety są dopiero od ww. wersji).
Najpierw obrazek:
Przykładowy kod:
// Windows conhost palette change test.
// gynvael.coldwind//vx
// Consider this code public domain
// (except the definitions; they are from MSDN; links below).
// Btw, this required Vista/2008 or newer version of windows.
#include <windows.h>
#include <stdio.h>
// Uncomment this if CONSOLE_SCREEN_BUFFER_INFOEX is undefined.
// - This seems to be the case in MinGW Platform API.
// - This is NOT the case for the newest Microsoft Windows Platform SDK.
// Source for these definitions: MSDN
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms686039(v=vs.85).aspx
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms683172(v=vs.85).aspx
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682091(v=vs.85).aspx
/*
typedef struct _CONSOLE_SCREEN_BUFFER_INFOEX {
ULONG cbSize;
COORD dwSize;
COORD dwCursorPosition;
WORD wAttributes;
SMALL_RECT srWindow;
COORD dwMaximumWindowSize;
WORD wPopupAttributes;
BOOL bFullscreenSupported;
COLORREF ColorTable[16];
} CONSOLE_SCREEN_BUFFER_INFOEX, *PCONSOLE_SCREEN_BUFFER_INFOEX;
extern "C" BOOL WINAPI GetConsoleScreenBufferInfoEx(
HANDLE hConsoleOutput,
PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx
);
extern "C" BOOL WINAPI SetConsoleScreenBufferInfoEx(
HANDLE hConsoleOutput,
PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx
);
*/
// Let's test the palette!
int
main(void)
{
// Set a black into violet gradient.
CONSOLE_SCREEN_BUFFER_INFOEX bi;
bi.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfoEx(hcon, &bi);
// Format: 0x00bbggrr
bi.ColorTable[ 0] = 0x000000; // black
bi.ColorTable[ 1] = 0x110011; // very dark violet
bi.ColorTable[ 2] = 0x330033;
bi.ColorTable[ 3] = 0x550055;
bi.ColorTable[ 4] = 0x770077;
bi.ColorTable[ 5] = 0x990099;
bi.ColorTable[ 6] = 0xbb00bb;
bi.ColorTable[ 7] = 0xdd00dd;
bi.ColorTable[ 8] = 0xff11ff; // violet
bi.ColorTable[ 9] = 0xff33ff;
bi.ColorTable[10] = 0xff55ff;
bi.ColorTable[11] = 0xff77ff; // pink
bi.ColorTable[12] = 0xff99ff;
bi.ColorTable[13] = 0xffbbff;
bi.ColorTable[14] = 0xffddff;
bi.ColorTable[15] = 0xffffff; // white
SetConsoleScreenBufferInfoEx(hcon, &bi);
// Test.
for(DWORD i = 0; i < 16; i++) {
// Change the color and print a test message.
SetConsoleTextAttribute(hcon, i);
printf("This is a test for color %u\n", (unsigned int)i);
// Buffering vs SetConsoleTextAttribute might be a bad idea.
fflush(stdout);
}
// Done.
return 0;
}
Update:
Ad polskie znaki diakrytyzowane (ąłść etc) w konsoli - tutaj trzeba pamiętać o jednej ważnej zasadzie: nieważne którą "polską" stronę kodową wybierzesz, ważne żeby edytor kodu / tekstu miał ustawioną dokładnie taką samą.
Czyli, jeśli masz edytor który zapisuje kod w utf-8, a stronę ustawisz jako windows-1250 (1250), to pojawią się krzaczki.
Prawdę mówiąc warto aby w ogóle nie trzymać stringów z polskimi znakami w kodzie - najlepiej trzymać je w jakimś pliku tekstowym i je sobie wczytać jako binarne dane. Warto również gdzieś na górze takowego pliku zamieścić informacje o użytym kodowaniu (tak aby następna osoba, która go będzie edytować, nie musiała zgadywać).
Anyway, przykładowy kod z kilkoma różnymi stronami kodowymi obsługującymi polskie znaki:
// Polish characters in Windows.
// gynvael.coldwind//vx
// Consider this code public domain
#include <windows.h>
#include <stdio.h>
int
main(void)
{
// Kazdy test zawiera nastepujace literki (diakrytyzowane):
// Aa Ss Zz Zz Oo
// ^^^^^
// pierwsze z kropeczka, drugie z kreseczka :)
// Przydatny link:
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx
// ibm852 -- OEM Latin 2; Central European (DOS)
// http://en.wikipedia.org/wiki/Code_page_852
SetConsoleOutputCP(852);
puts("Test strony kodowej 852 (ibm852):\n"
"\xA4\xA5 \x97\x98 \xBD\xBE \x8D\xAB \xE0\xA2\n");
fflush(stdout); // Buforowanie vs zmiana strony kodowej brzmi jak zly pomysl.
// windows-1250 -- ANSI Central European; Central European (Windows)
// http://en.wikipedia.org/wiki/Code_page_1250
SetConsoleOutputCP(1250);
puts("Test strony kodowej 1250 (windows-1250):\n"
"\xA5\xB9 \x8C\x9C \xAF\xBF \x8F\x9F \xD3\xF3\n");
fflush(stdout); // Buforowanie vs zmiana strony kodowej brzmi jak zly pomysl.
// iso-8859-2 -- ISO 8859-2 Central European; Central European (ISO)
// http://en.wikipedia.org/wiki/ISO/IEC_8859-2
SetConsoleOutputCP(28592);
puts("Test strony kodowej 28592 (iso-8859-2):\n"
"\xA1\xB1 \xA6\xB6 \xAF\xBF \xAC\xBC \xD3\xF3\n");
fflush(stdout); // Buforowanie vs zmiana strony kodowej brzmi jak zly pomysl.
// Skipping utf-7 since it shouldn't be used anyway.
// http://en.wikipedia.org/wiki/UTF-7#Security
// utf-8 -- Unicode (UTF-8)
// http://en.wikipedia.org/wiki/UTF-8
SetConsoleOutputCP(65001);
puts("Test strony kodowej 65001 (utf-8):\n"
"\xC4\x84\xC4\x85 \xC5\x9A\xC5\x9B \xC5\xBB\xC5\xBC "
"\xC5\xB9\xC5\xBA \xC3\x93\xC3\xB3\n");
// Moj edytor zapisuje w utf-8 wiec moglem po prostu napisac:
// "Ąą Śś Żż Źź Óó\n"
fflush(stdout); // Buforowanie vs zmiana strony kodowej brzmi jak zly pomysl.
// Done.
return 0;
}