Использование шрифта Unicode в консольном приложении C++

Как изменить шрифт в моем консольном приложении C++ для Windows?

Кажется, он не использует шрифт cmd.exe по умолчанию (Lucida Console). Когда я запускаю свое приложение через существующий cmd.exe (набрав name.exe), оно выглядит так: http://dathui.mine.nu/konsol3.png что совершенно верно. Но когда я запускаю свое приложение отдельно (дважды щелкнув по.exe), оно выглядит так: http://dathui.mine.nu/konsol2.png. Один и тот же код, два разных вида.

Поэтому теперь мне интересно, как я могу изменить шрифт, чтобы он всегда выглядел правильно, независимо от того, как он работает.


РЕДАКТИРОВАТЬ:

Хорошо, еще немного информации. Когда я просто использую этот маленький фрагмент:

SetConsoleOutputCP(CP_UTF8);
wchar_t s[] = L"èéøÞǽлљΣæča";
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
char* m = new char[bufferSize]; 
WideCharToMultiByte(CP_UTF8, 0, s, -1, m, bufferSize, NULL, NULL);
wprintf(L"%S", m);

это работает с правильным шрифтом. Но в моем реальном приложении я использую WriteConsoleOutput() вместо этого печатать строки:

CHAR_INFO* info = new CHAR_INFO[mWidth * mHeight];
for(unsigned int a = 0; a < mWidth*mHeight; ++a) {
    info[a].Char.UnicodeChar = mWorld.getSymbol(mWorldX + (a % mWidth), mWorldY + (a / mWidth));
    info[a].Attributes = mWorld.getColour(mWorldX + (a % mWidth), mWorldY + (a / mWidth));
}
COORD zero;
zero.X = zero.Y = 0;
COORD buffSize;
buffSize.X = mWidth;
buffSize.Y = mHeight;
if(!WriteConsoleOutputW(window, info, buffSize, zero, &rect)) {
    exit(-1);
}

и тогда он использует неправильный шрифт. Я использую два разных окна, созданные так:

mHandleA = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0,
                                     NULL, CONSOLE_TEXTMODE_BUFFER, NULL);

Могу ли я установить кодовую страницу только для стандартного вывода или что-то?

3 ответа

Решение

Для Vista и выше есть SetCurrentConsoleFontEx, как уже было сказано.

Для 2К и ХР есть недокументированная функция SetConsoleFont; например, прочитайте здесь.

typedef BOOL (WINAPI *FN_SETCONSOLEFONT)(HANDLE, DWORD);
FN_SETCONSOLEFONT SetConsoleFont;
..........
HMODULE hm = GetModuleHandle(_T("KERNEL32.DLL"));
SetConsoleFont = (FN_SETCONSOLEFONT) GetProcAddress(hm, "SetConsoleFont");
// add error checking
..........

SetConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), console_font_index);

Сейчас, console_font_index является индексом в таблице шрифтов консоли, определение которой неизвестно. Тем не мение, console_font_index == 10 известно, что идентифицирует Lucida Console (шрифт Unicode). Я не уверен, насколько стабильно это значение в разных версиях ОС.

ОБНОВИТЬ

После комментария Датта я провел эксперимент по чистой установке XP SP2.

  • Изначально GetNumberOfConsoleFonts() действительно возвращает 10, а индексы шрифтов 0..9 указывают различные растровые шрифты.

  • После того, как я открываю консоль с выбранным в ее свойствах шрифтом Lucida (только один раз; я могу закрыть его сразу после открытия, но эффект тот же), внезапно GetNumberOfConsoleFonts() начинает возвращать 12, а индексы 10 и 11 выбирают Lucida разных размеров,

Так что, похоже, этот трюк работал для меня, когда я играл с ним, потому что у меня всегда было запущено хотя бы одно консольное приложение с выбранным шрифтом Lucida.

Таким образом, для практических целей ответ Джона Хансона кажется лучше. Помимо предоставления лучшего контроля, это на самом деле работает.:)

Windows сохраняет настройки cmd (включая шрифт) в реестре, используя путь exe в качестве ключа. Корневым ключом является "HKEY_CURRENT_USER\Console", поэтому, если вы загляните туда с помощью regedit, вы должны увидеть несколько подразделов, названных в честь varous exe.

Чтобы скопировать настройки существующего exe-файла, вы можете экспортировать ключ в текстовый файл, затем отредактировать файл, чтобы изменить имя ключа на имя вашего exe-файла, а затем снова импортировать его.

Вы также можете программно изменять реестр, хотя я сомневаюсь, что это немедленно отразится на вашем окне консоли.

Вы можете попробовать функцию SetCurrentConsoleFontEx().

Другие вопросы по тегам