Directwrite 并不总是能够查询字体

问题描述 投票:0回答:1

使用 DirectWrite,我正在尝试获取 名为 Copyduck 的字体。

在我的 Windows 11 (10.0.22631.2861) 计算机上,我提供的代码没有找到该字体,但在我的 Windows 10 (10.0.19045.4046) 计算机上它找到了它。需要注意的是,在我的 Windows 11 机器中,在许多使用 directwrite 的应用程序中,我可以毫无问题地使用该字体。另外,我可以看到

C:\Windows\Fonts

中的字体。

重要注意事项。为了安装这个字体,我使用了

fontbase 并在其中激活 Copyduck。我想它使用 AddFontResource 并且似乎在 HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Fonts

 中添加字体。 Directwrite 无法查询由 
fontbase 激活的任何字体,这很奇怪,但我可以查询任何“系统”字体。

为什么会发生这种情况?为什么所有应用程序(如 Word、Photoshop、Aegisub、libass)都能够看到

fontbase 安装的字体,但我的小程序却看不到。

这是我的代码(PS:我在 Visual Studio 2022 中运行它):

#include <iostream> #include <dwrite_3.h> #pragma comment(lib, "Dwrite.lib") int main() { IDWriteFactory3* dwrite_factory; if (FAILED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(dwrite_factory), reinterpret_cast<IUnknown**>(&dwrite_factory)))) return 1; IDWriteFontSet* font_set; if (FAILED(dwrite_factory->GetSystemFontSet(&font_set))) return 1; std::wcout << L"There is " << font_set->GetFontCount() << L" fonts installed." << std::endl; DWRITE_FONT_PROPERTY_ID property_ids[] = { DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME, DWRITE_FONT_PROPERTY_ID_FULL_NAME, DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME, }; for (int i = 0; i < sizeof property_ids / sizeof * property_ids; i++) { DWRITE_FONT_PROPERTY property = { property_ids[i], L"Copyduck", L"", }; IDWriteFontSet* filtered_set; HRESULT hr = font_set->GetMatchingFonts(&property, 1, &filtered_set); if (FAILED(hr) || !filtered_set) continue; std::wcout << L"GetFontCount " << filtered_set->GetFontCount() << std::endl; filtered_set->Release(); } font_set->Release(); dwrite_factory->Release(); return 0; }
编辑 (15-03-2024)

在我的 Windows 11 机器中,我在较新的 gui 中看不到 Copyduck 字体(但是,正如我所说,我可以在旧版 GUI 中看到它,网址为

C:\Windows\Fonts

但是,在 Windows 10 上,我看到了

这很奇怪。我询问了一位通过将Windows 10升级到11来安装Windows 11的用户,他能够使用directwrite来查询fontbase安装的字体。

在 Windows 10 上,如果我有

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Fonts

 的条目,我可以直接使用 directwrite 查询它。但是,在 Windows 11 上,如果我输入了 
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Fonts
,directwrite 不会检测到字体!。需要注意的是,GDI 能够检测到它,因此它会在 GDI 和 Directwrite 之间造成不一致。

此时,我非常确定这是 Windows 11 中的一个错误。即使我真的不知道该怎么做,我也会尝试将其报告给微软。

com directwrite
1个回答
1
投票
当您使用

FontBase 并激活字体(文件)时,它会做两件事

    默认情况下,它会将文件复制到它拥有的文件夹中(如
  • c:\users\simon\fontbase
    )。
  • 它像这样设置注册表:

完成后,您可以在“旧”Windows UI 中看到此字体,其中该字体标有链接/快捷方式覆盖:

但是您在较新的 Windows UI 中看不到它:

有些程序可以使用它,我猜是因为它们手动读取注册表设置并直接加载指向的字体文件。

但是

DirectWrite

也无法读取它,可能是因为它不喜欢自定义文件夹,这可能是(我猜,找不到任何关于此的官方文档)一个安全问题,因为这个相对较新的功能

字体Microsoft Store 中的设置和字体 允许直接从应用程序商店安装字体。 因此,要使其正常工作,您可以将 FontBase 配置为指向 HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Fonts

下面的文件夹,如下所示:

PS:注意该文件夹可以是Fonts文件夹的子文件夹

现在一旦激活,DirectWrite 将看到它以及更新的 Windows UI:

顺便说一句,既然有了这个功能,安装字体就很简单了,你也可以自己修改注册表,把文件放到Fonts文件夹里,不需要FontBase之类的工具了。

否则,如果您确实想使用 FontBase 而无需重新配置它,您还可以编写一个 DirectWrite 自定义字体文件加载器,读取注册表并“手动”加载字体(但 DirectWrite 不会枚举它)。

© www.soinside.com 2019 - 2024. All rights reserved.