【问题标题】:Using Unicode font in C++ console app在 C++ 控制台应用程序中使用 Unicode 字体
【发布时间】:2010-12-27 16:41:47
【问题描述】:

如何更改我的 C++ Windows 控制台应用程序中的字体?

它似乎没有使用 cmd.exe 默认使用的字体(Lucida 控制台)。当我通过现有的 cmd.exe(键入 name.exe)运行我的应用程序时,它看起来像这样:http://dathui.mine.nu/konsol3.png 这是完全正确的。 但是当我单独运行我的应用程序(双击 .exe)时,它看起来像这样:http://dathui.mine.nu/konsol2.png。 相同的代码,两种不同的外观。

所以现在我想知道如何更改字体,使其无论运行方式如何都始终正确显示。


编辑:

好的,更多信息。当我只使用这个小sn-p时:

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);

我可以只为标准输出设置代码页吗?

【问题讨论】:

  • 嗯……很奇怪,有一种方法可以检测控制台与双击的情况,但有一些例外情况。这篇文章是一个好的开始,但还远远不够:codeguru.com/cpp/misc/misc/consoleapps/article.php/c15893
  • 你使用哪个编译器?
  • 也许跟踪启动代码 - 从 pre main() - 看看哪些代码实际上是在构建控制台窗口本身?我假设编译器/控制台项目提供的 .exe 中必须有代码,用于检测您的应用程序是否已经在控制台中启动,或者是否需要一个,在这种情况下会为您创建一个控制台窗口。这是我的直觉,不是经过研究的事实,但只需几分钟调试就可以验证。此时,您可以看到源代码,并查看您可能需要做什么才能访问该控制台 HWND,以不同方式设置其字体...
  • Ipthnc:听起来像是迂回的方式,但感谢您的提示。 SjB:Visual Studio 2008 教授。 Mordachai:嗯,我在哪里可以找到 pre-main 代码?

标签: c++ winapi unicode fonts console-application


【解决方案1】:

Windows 使用 exe 路径作为键将 cmd 设置(包括字体)存储在注册表中。根键是“HKEY_CURRENT_USER\Console”,所以如果你用 regedit 看一下,你应该会看到几个以各种 exe 命名的子键。

要复制现有 exe 的设置,您可以将密钥导出到文本文件,然后编辑文件以将密钥名称更改为您的 exe 的名称,然后重新导入。

您也可以通过编程方式修改注册表,但我怀疑这会立即生效 w.r.t。到您的控制台窗口。

【讨论】:

    【解决方案2】:

    你可以试试SetCurrentConsoleFontEx()函数。

    【讨论】:

    • 您可能还想提及 GetStdHandle - msdn.microsoft.com/en-us/library/ms683231(VS.85).aspx
    • iirc 仅存在于 vista 及更高版本,更喜欢这在 xp 上也是可行的,因为很多人仍在运行它。
    • 奇怪,他们声称您需要 Vista,但还声称您应该将 _WIN32_WINNT 定义为 0x0500 (Windows 2000) 或更高版本。看起来很矛盾。
    • 马克,这可能只是一个错字——应该是 6 而不是 5。
    【解决方案3】:

    对于 Vista 及更高版本,有 SetCurrentConsoleFontEx,已经有 said

    对于 2K 和 XP,有一个未记录的函数 SetConsoleFont;例如阅读here

    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's answer 似乎更好。除了提供更好的控制外,它确实有效。 :)

    【讨论】:

    • 它确实改变了字体,但 GetNumberOfConsoleFonts() 为我返回 10,我尝试了 0-9(和 10,11,...),但这些都不是 Lucida Console。所以现在的问题是,我如何使用它来更改为 Lucida 控制台? :)
    猜你喜欢
    • 2013-03-04
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 2014-05-03
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多