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

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

Кажется, он не использует шрифт, который cmd.exe использует по умолчанию (консоль Lucida). Когда я запускаю свое приложение через существующий 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);

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


person dutt    schedule 17.12.2009    source источник
comment
Хм ... странно, есть способ определить консоль против двойного щелчка с несколькими исключительными случаями. Эта статья — хорошее начало, но ее недостаточно: codeguru.com/cpp/misc/misc/consoleapps/article.php/c15893   -  person Hamish Grubijan    schedule 17.12.2009
comment
Какой компилятор вы используете?   -  person Sajad Bahmani    schedule 17.12.2009
comment
Возможно, проследите код запуска — от pre main() — чтобы увидеть, какой код на самом деле создает само окно консоли? Я предполагаю, что должен быть код, который является частью вашего .exe, предоставленного проектом компилятора/консоли, который определяет, запускается ли ваше приложение уже в консоли или если оно ему нужно, и в этом случае создает окно консоли для вас. Это моя интуиция, а не исследованные факты, но их можно проверить всего за несколько минут отладки. В этот момент вы можете увидеть источник для этого и посмотреть, что вам может понадобиться сделать, чтобы получить доступ к этой консоли HWND, чтобы установить ее шрифт по-другому...   -  person Mordachai    schedule 17.12.2009
comment
Ipthnc: звучит как окольный путь, но спасибо за подсказку. SjB: Visual Studio 2008 проф. Мордахай: Хм, а где мне найти предварительный код?   -  person dutt    schedule 17.12.2009


Ответы (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.

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

person atzz    schedule 17.12.2009
comment
Он меняет шрифт, но GetNumberOfConsoleFonts() возвращает мне 10, и я пробовал 0-9 (и 10,11,...), но ни один из них не был консолью Lucida. Итак, теперь вопрос в том, как мне использовать это, чтобы перейти на консоль Lucida? :) - person dutt; 17.12.2009

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

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

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

person jon-hanson    schedule 17.12.2009

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

person Ferruccio    schedule 17.12.2009
comment
Вы также можете упомянуть GetStdHandle — msdn.microsoft.com /en-us/library/ms683231(VS.85).aspx - person Mark Ransom; 17.12.2009
comment
iirc, который существует только в Vista и более поздних версиях, предпочитаю, чтобы это было выполнимо и на XP, поскольку многие люди все еще используют его. - person dutt; 17.12.2009
comment
Странно, они утверждают, что вам нужна Vista, но также утверждают, что вы должны определить _WIN32_WINNT как 0x0500 (Windows 2000) или более позднюю версию. Кажется противоречивым. - person Mark Ransom; 17.12.2009
comment
Марк, возможно, это просто опечатка — вместо 5 должно было быть 6. - person Rob Kennedy; 17.12.2009