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