【问题标题】:How can I use SetCurrentConsoleFontEx with fonts loaded by AddFontMemResourceEx?如何将 SetCurrentConsoleFontEx 与 AddFontMemResourceEx 加载的字体一起使用?
【发布时间】:2020-12-04 20:59:00
【问题描述】:

我的主要目标是使用 Windows API 函数将控制台字体设置为 Unifont。我可以通过使用文件名调用AddFontResource 来成功地做到这一点。我宁愿使用AddFontMemResourceEx,因为这样我就可以从资源中加载字体。 我测试了各种加载字体的调用,结果如下:

AddFontResource(filename); //works
AddFontResourceEx(filename, FR_PRIVATE, NULL); //does not work
AddFontResourceEx(filename, FR_NOT_ENUM, NULL); //works
AddFontMemResourceEx(valid_pointer, data_size, NULL, &font_count); //does not work

我使用 Unifont 和 Fira Code 两种字体(我能找到的唯一一种会显示在终端上的字体)对它们进行了测试。

我编写这个程序是为了消除将字体作为资源加载时可能出现的问题。

#include <windows.h>
#include <iostream>
#include <fstream>
#include <filesystem>

int main() {
    std::string filename = "unifont-13.0.04.ttf";
    std::wstring fontname = L"Unifont";

    auto fileSize = std::filesystem::file_size(filename);
    std::ifstream in(filename, std::ifstream::binary);

    char* data = new char[fileSize];
    in.read(data, fileSize);
    in.close();

    DWORD loadedFonts = 0;
    AddFontMemResourceEx(reinterpret_cast<PVOID>(data), fileSize, NULL, &loadedFonts);

    CONSOLE_FONT_INFOEX cfi;
    cfi.cbSize = sizeof(cfi);
    cfi.nFont = 0;
    cfi.dwFontSize.X = 0;
    cfi.dwFontSize.Y = 16;
    cfi.FontFamily = FF_DONTCARE;
    cfi.FontWeight = FW_NORMAL;
    wcscpy_s(cfi.FaceName, fontname.c_str());

    SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &cfi);

    std::wcout << "I found " << loadedFonts << " fonts.";
    std::wcin.ignore();

    delete[] data;
}

使用 unifont,AddFontMemResourceEx 会将 loadedFonts 设置为 2,表示它确实找到并加载了两种字体,并且没有失败。

值得注意的是,SetCurrentConsoleFontEx 返回的HANDLE 除了调用RemoveFontMemResourceEx 之外完全没有用处,在大多数情况下您甚至不需要这样做,因为在进程结束时字体将被卸载。

为什么SetCurrentConsoleFontEx 可以与AddFontResource 一起使用,但不能与AddFontMemResourceEx 一起使用?

【问题讨论】:

  • 这不行,控制台由不同的进程(conhost.exe)拥有。
  • @HansPassant 所以问题是字体是在我的进程中加载​​的,但是SetCurrentConsoleFontEx 将字体名称发送到 conhost.exe,它没有加载该字体。

标签: c++ winapi


【解决方案1】:

来自doc

此函数允许应用程序获取嵌入的字体 文档或网页。 AddFontMemResourceEx添加的字体 对发出调用的进程始终是私有,而不是 可枚举的。

其他内容请参考zett42's answer

您正在使用 FR_PRIVATE 标志调用 AddFontResourceEx(),这意味着 该字体仅适用于您的进程。

很遗憾,控制台窗口不是您进程的一部分 (GetWindowThreadProcessId() 就在这方面!)。它由一个 系统进程(Win 7之前的“csrss.exe”,之后的“conhost.exe”)。

【讨论】:

    猜你喜欢
    • 2018-11-30
    • 2020-09-30
    • 2018-07-31
    • 2012-06-21
    • 2011-08-19
    • 2013-07-15
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    相关资源
    最近更新 更多