Delphi 从资源文件加载字体

Delphi 从资源文件加载字体,delphi,delphi-xe,Delphi,Delphi Xe,我有一个Delphi XE项目,其中包含以下资源: 我使用并尝试了以下代码: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Label1: TLabel; Label2: TLabel; procedure

我有一个Delphi XE项目,其中包含以下资源:

我使用并尝试了以下代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function LoadResourceFontByName( const ResourceName : string; ResType: PChar ) : Boolean;
var
  ResStream  : TResourceStream;
  FontsCount : DWORD;
begin
  ResStream := TResourceStream.Create(hInstance, ResourceName, ResType);
  try
    Result  := (AddFontMemResourceEx(ResStream.Memory, ResStream.Size, nil, @FontsCount) <> 0);
  finally
    ResStream.Free;
  end;
end;

function LoadResourceFontByID( ResourceID : Integer; ResType: PChar ) : Boolean;
var
  ResStream  : TResourceStream;
  FontsCount : DWORD;
begin
  ResStream := TResourceStream.CreateFromID(hInstance, ResourceID, ResType);
  try
    Result  := (AddFontMemResourceEx(ResStream.Memory, ResStream.Size, nil, @FontsCount) <> 0);
  finally
    ResStream.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  if LoadResourceFontByName('MyFont1', RT_RCDATA) then Label1.Font.Name := 'My Custom Font1';
  if LoadResourceFontByID(2, RT_FONT) then Label2.Font.Name := 'My Custom Font2';   
end.
单元1;
接口
使用
窗口、消息、系统工具、变体、类、图形、控件、窗体、,
对话框,stdctrl;
类型
TForm1=类(TForm)
标签1:TLabel;
标签2:TLabel;
过程表单创建(发送方:ToObject);
私有的
{私有声明}
公众的
{公开声明}
结束;
变量
表1:TForm1;
实施
{$R*.dfm}
函数LoadResourceFontByName(const ResourceName:string;ResType:PChar):布尔;
变量
ResStream:TResourceStream;
丰斯康特:德沃德;
开始
ResStream:=TResourceStream.Create(hInstance、ResourceName、ResType);
尝试
结果:=(AddFontMemResourceEx(ResStream.Memory,ResStream.Size,nil,@FontScont)0);
最后
免费的;
结束;
结束;
函数LoadResourceFontByID(ResourceID:Integer;ResType:PChar):布尔;
变量
ResStream:TResourceStream;
丰斯康特:德沃德;
开始
ResStream:=TResourceStream.CreateFromID(hInstance,ResourceID,ResType);
尝试
结果:=(AddFontMemResourceEx(ResStream.Memory,ResStream.Size,nil,@FontScont)0);
最后
免费的;
结束;
结束;
过程TForm1.FormCreate(发送方:TObject);
开始
如果LoadResourceFontByName('MyFont1',RT_RCDATA),则Label1.Font.Name:='My Custom Font1';
如果LoadResourceFontByID(2,RT_字体),则Label2.FONT.Name:=“我的自定义Font2”;
结束。
顺便说一下:我知道如果我需要将字体嵌入我的EXE文件,我应该拥有字体的重新分发权限

但问题是,如果字体名称(我使用了我的自定义字体1我的自定义字体2)不是字体的实际名称,则字体无法正确加载并显示未知字体字符


我的问题是,尽管我在founctions中使用了
ResStream.Free
,但我必须重新定义
FormClose
FormDestroy
事件来保护内存泄漏
标签。Font
没有下标,因此
Label2.Font[2]
无效

此外,将
loadfontsource
函数的布尔结果指定给
标签。任何类型的Font
显然都不起作用,因为该布尔结果永远不会是Font


我建议您先学习使用Delphi编程的基础知识,并学习TFont的VCL/FMX文档,然后再考虑从内存加载自定义字体。

您的代码中有几个错误

  • LoadResourceFont()
    返回一个
    布尔值。您正试图将该值分配给
    TLabel.Font.Name
    属性,但由于
    布尔值
    不是
    字符串,因此无法执行此操作。您还试图将
    Boolean
    赋值给
    TLabel.Font[2]
    属性,该属性甚至不是可赋值的有效标识符

  • 您对
    LoadResourceFont()
    的第一次调用指定了错误的资源名称

  • LoadResourceFont()
    的第一个参数是一个
    String
    ,但是对
    LoadResourceFont()
    的第二个调用试图传递一个全局
    Hinstance
    变量(一个
    THandle
    ),其中需要一个
    字符串

  • 您试图将第二种字体作为RCDATA资源加载,而实际上它是一种字体资源

  • 要执行您正在尝试的操作,首先需要调用
    LoadResourceFont()
    将字体加载到字体表中,然后可以将
    TLabel.font.Name
    设置为所需字体的字体名称(TTF文件中定义的名称,而不是文件名或资源名),例如:

    函数LoadResourceFontByName(const ResourceName:string;ResType:PChar):布尔值;
    变量
    ResStream:TResourceStream;
    丰斯康特:德沃德;
    开始
    ResStream:=TResourceStream.Create(hInstance、ResourceName、ResType);
    尝试
    结果:=(AddFontMemResourceEx(ResStream.Memory,ResStream.Size,nil,@FontScont)0);
    最后
    免费的;
    结束;
    结束;
    函数LoadResourceFontByID(ResourceID:Integer;ResType:PChar):布尔;
    变量
    ResStream:TResourceStream;
    丰斯康特:德沃德;
    开始
    ResStream:=TResourceStream.CreateFromID(hInstance,ResourceID,ResType);
    尝试
    结果:=(AddFontMemResourceEx(ResStream.Memory,ResStream.Size,nil,@FontScont)0);
    最后
    免费的;
    结束;
    结束;
    过程TForm1.FormCreate(发送方:TObject);
    开始
    如果LoadResourceFontByName('MyFont1',RT_RCDATA),则
    Label1.Font.Name:=“我的字体名称1”;
    如果LoadResourceFontByID(2,RT_字体),则
    Label2.Font.Name:=“我的字体名称2”;
    结束;
    
    “Label2.Font[2]”为什么要编译它?您希望该语句是什么意思?我需要从RCDATA Type资源加载Label1字体,从Font Type资源加载Label2字体。查找函数的定义如何?这将阻止您为字符串指定布尔值。它还将告诉您如何处理函数的返回值。您需要添加字体,然后检查是否成功。你不能那样做。然后,您可以按名称引用该字体,就像其他字体一样。就这样。考虑代码的作用而不是盲目复制代码是值得的。读一下。理解它。想想它能做什么。阅读文档。不要盲目抄袭,在没有任何理解的情况下随意尝试。@Ken,好的,我明白了,谢谢你的纠正。我不确定这是否真的回答了问题。真的,这并没有解决我的问题。我需要编译并正确运行我的代码。@Rob:问题是我无法编译。我解释了为什么它不会编译——由于我描述的原因,它是无效代码。没有提出其他问题或描述其他问题(标题没有
    function LoadResourceFontByName( const ResourceName : string; ResType: PChar ) : Boolean;
    var
      ResStream : TResourceStream;
      FontsCount : DWORD;
    begin
      ResStream := TResourceStream.Create(hInstance, ResourceName, ResType);
      try
        Result := (AddFontMemResourceEx(ResStream.Memory, ResStream.Size, nil, @FontsCount) <> 0);
      finally
        ResStream.Free;
      end;
    end;
    
    function LoadResourceFontByID( ResourceID : Integer; ResType: PChar ) : Boolean;
    var
      ResStream : TResourceStream;
      FontsCount : DWORD;
    begin
      ResStream := TResourceStream.CreateFromID(hInstance, ResourceID, ResType);
      try
        Result := (AddFontMemResourceEx(ResStream.Memory, ResStream.Size, nil, @FontsCount) <> 0);
      finally
        ResStream.Free;
      end;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      if LoadResourceFontByName('MyFont1', RT_RCDATA) then
        Label1.Font.Name := 'My Font Name 1';
    
      if LoadResourceFontByID(2, RT_FONT) then
        Label2.Font.Name := 'My Font Name 2';
    end;