Firemonkey: 如何将资源中的字体添加到内存中并使用它

9

VCL 中,我可以从资源中加载字体,并在不保存它的情况下直接从内存中使用。

下面是我在 VCL 中使用的代码,它可以正常工作:

procedure TForm1.Button1Click(Sender: TObject);
var
   ResStream  : tResourceStream;
   FontsCount : DWORD;
begin
   ResStream  := tResourceStream.Create(hInstance, 'MyResourceName', RT_RCDATA);
   winapi.windows.AddFontMemResourceEx(ResStream.Memory, ResStream.Size, nil, @FontsCount);
   ResStream.Free();
   button1.Font.name := 'MySavedFontNameInResource';
end;
在Firemonkey中,我刚刚将button1.Font.name更改为button1.Font.family,但不幸的是字体没有改变。所以我认为这段代码与firemonkey不兼容。那么在Firemonkey中,如何从资源中加载字体并将其暂时保存到内存中,并直接从内存中使用它呢?
更新:
我看到了这些页面:在Firemonkey中安装字体如何使用外部字体? 根据Mr Ed的回答,在FMX中似乎没有解决此问题的方法。但是也许如果我们在运行应用程序之前先安装字体,就可以加载字体。我几乎尝试了一切,但仍然无法加载字体。

我假设你的函数在VCL和FMX两种情况下都能成功运行? - Free Consulting
当然,它编译通过了,因为语法是正确的。问题是,在这两种情况下,它是否返回成功状态?请尽可能检查错误。 - Free Consulting
@ 在VCLFMX中,该函数返回true。我不知道但我觉得FontsCount: integer;有问题。我把integer改成了DWORD但是没有任何变化(http://msdn.microsoft.com/en-us/library/windows/desktop/dd183325(v=vs.85).aspx) - Sky
我已经没有更多的想法了,抱歉。但是我想指出对于任何未来的读者,加载字体资源可以正常工作(请参见修订记录),并且在某些FMX字体字符串处理中可能存在问题(也许不可枚举的字体会产生一些影响)。 - Free Consulting
可能相关:http://stackoverflow.com/a/18413827/205376 - Free Consulting
显示剩余5条评论
3个回答

1

这可能有所帮助,也可能没有。

免责声明

这需要额外的研究,我还没有开始,但我认为这是一个很好的起点。

MSDN页面链接:自定义字体集

您需要使用WinAPI.D2D1单元(您可能还需要FMX.TextLayout和FMX.Canvas.D2D)来访问DirectWrite API。您可以使用此功能来获取DirectWrite工厂,从而允许您定义并从磁盘加载字体。

一旦您加载了字体,据我所知,它应该可供整个应用程序使用,并且希望所有FireMonkey控件都可用。然而,FireMonkey可能仅在应用程序加载时枚举字体,因此这可能都是徒劳无功。

正如我所说,这需要我尚未进行的研究,因此只有在您也自定义绘制控件(我将会这样做)时才能起作用,因此可能不适合。


1
在新的 Delphi 中还有一个 StylesSettings.ssFamily: Boolean 属性,必须设置为 False 才能使用自定义字体族。大小、样式和字体颜色也是如此。

我认为这不是原因,因为当我将 button1.Font.name := 'MyFontName'; 中的 MyFontName 更改为现有字体(如Tahoma或Segoe UI)时,字体会更改。 - Sky
1
尝试使用按钮字体大小;-) - Sebastian Xawery Wiśniowiecki
将TButton放置在默认的TForm上,将字体大小设置为55,然后转到StyledSettings并切换ssSize复选框 - 然后看看在切换时TButton上的文本会发生什么! - Sebastian Xawery Wiśniowiecki
我知道你的意思。但我的问题不是关于StylesSettings。正如我在第一条评论中所说,我可以更改字体。 - Sky
当我在设计时选择新的字体族时,它有效。如果你想在运行时做同样的事情,我认为你应该使用样式。使用TStyleBook设计新的按钮样式,并在运行时更改它 :) - Sebastian Xawery Wiśniowiecki

0

我认为我有一个答案,这只有在Embarcadero支持团队的Roy Nelson的大量帮助下才有可能,他指引了我正确的方向。

我已经验证了这个方法适用于64位Windows 10上的Berlin 10.1(未应用周年补丁),但我不能保证它适用于所有编译器版本/Windows版本,其他人提供的任何见解都将非常有趣。

首先,我认为(目前)无法克服的问题始于尝试使用AddFontMemResourceEx,因为它生成的字体是不可枚举的,而对于Firemonkey将安装的TrueType字体转换为图形渲染的D2D字体 - 这实际上是它使用的东西 - 它必须首先能够找到它。

用从资源中编写的临时字体文件替换AddFontMemResourceEx可以解决这个问题,但这还不够。 安装后,您需要强制TextLayout渲染引擎重建其字体列表,您可以通过调用FMX.Canvas.D2D.pas单元中的两行来完成。

UnregisterCanvasClasses; //this tells it to forget everything it knows
RegisterCanvasClasses; //this tells it to learn it again based on the current state of this system, which now includes our dynamically loaded font.

我已经在GitHub上发布了一个测试项目https://github.com/TheOriginalBytePlayer/FireMonkey-Fonts,供想要尝试的人使用。
基本上,您需要创建一个包含字体资源的资源文件——从0到任何数字——将FMXFontInstaller.pas中的{$R assimilate.res}行替换为您刚创建的行,并将此文件添加到您的项目源中,理论上您就可以开始使用了。

1
顺便说一下,我认为这是一种极不优雅的做法,我正在推动Embarcadero使其自动适用于项目的Images/Resources中安装的任何字体,无论是在Mac还是Windows上。如果您同意,可以为原始错误报告投票https://quality.embarcadero.com/browse/RSP-17030。 - Byte Player
嗯...我在一台运行Windows 7的64位机器上测试了它,但没成功。除了“哦,糟糕。”,还有人有什么想法吗? - Byte Player

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接