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

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

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

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


EDIT:

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

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

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

Ответы

Ответ 1

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

Для 2K и XP существует недокументированная функция 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). Я не уверен, насколько это стабильное значение для разных версий ОС.

UPDATE

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

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

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

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

Таким образом, для практических целей jon hanson answer кажется лучше. Кроме того, предлагая лучший контроль, он действительно работает.:)

Ответ 2

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

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

Вы также можете progmatically изменить реестр, хотя я сомневаюсь, что это немедленно вступит в силу w.r.t. в окно консоли.