Използване на 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);

Може ли да задавам кодовата страница само за стандартния изход или нещо подобно?


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 проф. Mordachai: Хм, къде мога да намеря предварителния основен код?   -  person dutt    schedule 17.12.2009


Отговори (3)


За Vista и по-нова версия има SetCurrentConsoleFontEx , както вече беше казано.

За 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). Не съм сигурен колко стабилна е тази стойност в различните версии на ОС.

АКТУАЛИЗАЦИЯ

След коментара на dutt, проведох експеримент върху чиста настройка на XP SP2.

  • Първоначално GetNumberOfConsoleFonts() наистина връща 10, а индексите на шрифтове 0..9 определят различни растерни шрифтове.

  • След като отворя конзола с избран шрифт Lucida в нейните свойства (само веднъж; мога да я затворя веднага след отваряне, но ефектът е същият), изведнъж GetNumberOfConsoleFonts() започва да връща 12, а индекси 10 и 11 избират Lucida с различни размери .

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

По този начин, за практически цели, отговорът на jon hanson изглежда По-добре. Освен че предлага по-добър контрол, той наистина работи. :)

person atzz    schedule 17.12.2009
comment
Променя шрифта, но GetNumberOfConsoleFonts() връща 10 за мен и аз опитах 0-9 (и 10,11,...), но нито едно от тях не беше Lucida Console. Така че сега въпросът е как да използвам това, за да премина към конзола Lucida? :) - person dutt; 17.12.2009

Windows съхранява cmd настройките (включително шрифта) в системния регистър, като използва exe пътя като ключ. Основният ключ е „HKEY_CURRENT_USER\Console“, така че ако погледнете там с regedit, трябва да видите няколко подключа, наречени на различни exe файлове.

За да копирате настройките на съществуващ exe, можете да експортирате ключа в текстов файл, след което да редактирате файла, за да промените името на ключа с това на вашия exe, след което да го импортирате отново.

Можете също така да промените програмно регистъра, въпреки че се съмнявам, че това ще влезе в сила незабавно. към прозореца на вашата конзола.

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
Марк, това вероятно е само печатна грешка — трябваше да е 6 вместо 5. - person Rob Kennedy; 17.12.2009