【发布时间】: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,它没有加载该字体。