2017-02-17 34 views
0

Lucida Console предустановлен шрифт TTF в Windows 7, и я хотел бы программно установить его в консольном приложении.Как программно настроить шрифт консоли для Lucida?

  1. По какой-то причине SetCurrentConsoleFontEx «даже не объявлен в этой области». I #include <windows.h>, где он должен быть определен.

  2. Что бы я положил в CONSOLE_FONT_INFOEX?

  3. #define _WIN32_WINNT 0x0601, как @Alf предлагает, не имеет никакого эффекта

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

Он должен работать на Windows XP +, я использую MinGW г ++ 4.8.1 на Windows 7.

+0

В зависимости от вашего компилятора вам может понадобиться [define '_WIN32_WINNT', прежде чем включать' '] (https://msdn.microsoft.com/en-us/library/6sehtctf.aspx). Функция, которую вы хотите использовать, кажется, не доступна для Windows XP, требующей Windows Server 2008. –

+0

В Windows XP я думаю, что вы можете сделать это громоздким путем, изменив информацию для окна консоли. Насколько я помню, местоположение относится к способу запуска окна. Если из ярлыка он хранится в ярлыке, и в противном случае он сохраняется в реестре. –

+0

FWIW 'SetcurrentConsoleFontEx' должен быть' SetCurrentConsoleFontEx'. Если вы ошибаетесь в одном месте ... –

ответ

1

Если SetCurrentConsoleFontEx и CONSOLE_FONT_INFOEX не существует даже после установки _WIN32_WINNT то вы используете устаревший SDK. Не редкость с MinGW, потому что он использует неофициальные сторонние файлы заголовков.

Работа с консольными шрифтами в Windows проблематична, потому что консоль хранит свои шрифты во внутреннем массиве. Возможно, вам также придется использовать некоторые недокументированные функции.

В Vista и позже требуется только то, что нужно позвонить SetCurrentConsoleFontEx. Проблема, конечно, в том, что документация действительно плохая, а структура CONSOLE_FONT_INFOEX используется как для функций Set, так и для Get, не сообщая вам, какие члены используются.

При установке только кажется, требуют, чтобы установить cbSize и FaceName, все остальное может быть равен нулю:

HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 
CONSOLE_FONT_INFOEX cfie; 
ZeroMemory(&cfie, sizeof(cfie)); 
cfie.cbSize = sizeof(cfie); 
lstrcpyW(cfie.FaceName, L"Lucida Console"); 
SetCurrentConsoleFontEx(hStdOut, false, &cfie); 

Если вы хотите установить конкретный размер шрифта можно установить dwFontSize.Y. Будьте осторожны с FontFamily, если вы установите неправильное значение, Windows вернется к шрифту терминала по умолчанию.

На предварительно Vista, системах единственное, что вы можете получить доступ в массив шрифта является размер:

#if 1 // Using old SDK? 
typedef struct _CONSOLE_FONT_INFOEX { 
ULONG cbSize; 
DWORD nFont; 
COORD dwFontSize; 
UINT FontFamily; 
UINT FontWeight; 
WCHAR FaceName[LF_FACESIZE]; 
} CONSOLE_FONT_INFOEX, *PCONSOLE_FONT_INFOEX; 
typedef BOOL (WINAPI*SETCURRENTCONSOLEFONTEX)(HANDLE hConsoleOutput,BOOL bMaximumWindow,CONSOLE_FONT_INFOEX*lpConsoleCurrentFontEx); 
SETCURRENTCONSOLEFONTEX SetCurrentConsoleFontEx = (SETCURRENTCONSOLEFONTEX) GetProcAddress(LoadLibraryA("KERNEL32"), "SetCurrentConsoleFontEx"); 
typedef BOOL (WINAPI*GETCURRENTCONSOLEFONTEX)(HANDLE hConsoleOutput,BOOL bMaximumWindow,CONSOLE_FONT_INFOEX*lpConsoleCurrentFontEx); 
GETCURRENTCONSOLEFONTEX GetCurrentConsoleFontEx = (GETCURRENTCONSOLEFONTEX) GetProcAddress(LoadLibraryA("KERNEL32"), "GetCurrentConsoleFontEx"); 
#endif 

static DWORD PrintFontInfoNT4(HANDLE hCon) 
{ 
    CONSOLE_FONT_INFO cfi; 
    BOOL succ = GetCurrentConsoleFont(hCon, false, &cfi); 
    printf("Get succ=%d nFont=%u dwFontSize=%dx%d\n", succ, cfi.nFont, cfi.dwFontSize.X, cfi.dwFontSize.Y); 
    return succ ? cfi.nFont : -1; 
} 

static DWORD PrintFontInfoNT6(HANDLE hCon) 
{ 
    CONSOLE_FONT_INFOEX cfie; 
    ZeroMemory(&cfie, sizeof(cfie)); 
    cfie.cbSize = sizeof(cfie); 
    BOOL succ = GetCurrentConsoleFontEx(hCon, false, &cfie); 
    printf("GetEx succ=%d nFont=%u size=%dx%d fam=%#x wei=%u name=%ls\n", succ, cfie.nFont, cfie.dwFontSize.X, cfie.dwFontSize.Y, cfie.FontFamily, cfie.FontWeight, cfie.FaceName); 
    return succ ? cfie.nFont : -1; 
} 

static void TestNT4() 
{ 
    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 
    typedef DWORD (WINAPI*GETNUMBEROFCONSOLEFONTS)(); 
    GETNUMBEROFCONSOLEFONTS GetNumberOfConsoleFonts = (GETNUMBEROFCONSOLEFONTS) GetProcAddress(LoadLibraryA("KERNEL32"), "GetNumberOfConsoleFonts"); 
    typedef BOOL (WINAPI*SETCONSOLEFONT)(HANDLE hConOut, DWORD nFont); 
    SETCONSOLEFONT SetConsoleFont = (SETCONSOLEFONT) GetProcAddress(LoadLibraryA("KERNEL32"), "SetConsoleFont"); 

    // This is the best you can do on NT/2000/XP/2003 without hacks 
    DWORD orgFont = PrintFontInfoNT4(hStdOut); 
    printf("GetNumberOfConsoleFonts=%u orgFont=%u\n", GetNumberOfConsoleFonts(), orgFont); 
    for (DWORD i = 0, c = GetNumberOfConsoleFonts(); i < c; ++i) 
    { 
     SetConsoleFont(hStdOut, i); 
     PrintFontInfoNT4(hStdOut); 
#if _WIN32_WINNT >= 0x0600 
     PrintFontInfoNT6(hStdOut); 
#endif 
     Sleep(1000); 
    } 
    SetConsoleFont(hStdOut, orgFont); // Restore the original font 
} 

Это довольно бесполезно, потому что вы не можете сказать, какой шрифт вы настраиваете. Если вы все еще настаиваете на настройке шрифта в системах до Vista, вы должны заразиться руками. Сначала вам нужно решить, какие окна терминала вы хотите применить.

Терминалы по умолчанию хранятся под HKEY_CURRENT_USER\Console, а настройки для каждого приложения могут быть сохранены в под-ключах. Эти значения по умолчанию могут быть overridden, если приложение запускается ярлыком.

Если вы хотите изменить консоль, в которой работаете, тогда все становится еще сложнее, но сама Windows, конечно же, знает, как установить шрифт напрямую. Вы можете увидеть это в действии, когда вы выбираете «Свойства» в меню консолей и применяете изменение шрифта. Вероятно, это может измениться с версии на версию, но я считаю, что она использует сопоставленную память и секретное сообщение.Вы можете начать свое исследование, установив точку останова в WinDbg; после правильной настройки символов введите bp console!Write*ВкладкаВведите (установите его на все функции записи, если их несколько). Вам нужно будет разобраться в макете используемой структуры, поэтому вам может потребоваться применить к ней одну консольную настройку и сбросить/сравнить память.

Edit:

Похоже, что некоторые люди уже поняли это. This bug analysis paper имеет определение структуры, а также found a SetConsolePalette function, который реализует трюк с отображенной памятью. ReactOS может не использовать ту же самую реализацию, но вы также можете использовать take a look at it.

Вам все равно необходимо вызвать SetCurrentConsoleFontEx в системах, которые имеют его, потому что внутренности, вероятно, изменились, когда Windows начала использовать conhost.exe.

+0

Может показаться хорошей идеей четко указать, что версия до Vista подходит для недокументированных деталей реализации, которые могут быть изменены без предварительного уведомления. – IInspectable