Jan*_*roň 3 c++ windows mingw console-application
Lucida Console 是 Windows 7 上预安装的 TTF 字体,我想以编程方式在控制台应用程序中设置它。
由于某种原因,SetCurrentConsoleFontEx “甚至没有在此范围内声明”。我#include <windows.h>应该在哪里定义它。
我会在CONSOLE_FONT_INFOEX中放入什么?
#define _WIN32_WINNT 0x0601正如@Alf建议的那样,没有效果
右键单击控制台标题并在那里手动选择字体很容易,但我宁愿在代码中执行此操作。
它应该在 Windows XP+ 上运行,我在 Windows 7 上使用 MinGW g++ 4.8.1。
如果设置后SetCurrentConsoleFontEx和CONSOLE_FONT_INFOEX也不存在,_WIN32_WINNT那么您使用的是过时的 SDK。MinGW 并不罕见,因为它使用非官方的第 3 方头文件。
在 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);
Run Code Online (Sandbox Code Playgroud)
如果您想设置特定的字体大小,可以设置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
}
Run Code Online (Sandbox Code Playgroud)
这是非常无用的,因为你无法分辨你正在设置哪种字体。如果您仍然坚持在 Vista 之前的系统上设置字体,您就必须亲自动手。首先,您需要决定要将更改应用到哪些终端窗口。
终端默认值存储在子键中HKEY_CURRENT_USER\Console,每个应用程序的设置可以存储在子键中。如果应用程序是通过快捷方式启动的,则可以覆盖这些默认值。
如果您只想更改正在运行的控制台,那么事情会变得更加困难,但 Windows 本身当然知道如何直接设置字体。当您在控制台菜单中选择“属性”并应用字体更改时,您可以看到它的实际效果。这可能会因版本而异,但我相信它使用映射内存和秘密消息。您可以通过在WinDbg中设置断点来开始调查;正确设置符号后,键入bp console!Write* TabEnter(如果有多个写入功能,请在所有写入功能上设置)。您必须弄清楚它正在使用的结构的布局,因此您可能必须同时应用一种控制台设置并转储/比较内存。
编辑:
看来有些人已经明白了这一点。这篇错误分析论文有一个结构体定义,我还发现了一个实现映射内存技巧的SetConsolePalette 函数。ReactOS 可能不会使用完全相同的实现,但您也可以看一下它。
您仍然需要在具有 SetCurrentConsoleFontEx 的系统上调用它,因为当 Windows 开始使用 conhost.exe 时,内部结构可能会发生变化。