-2

I am having a Delphi XE Project with the following resource:

Project1

I have used function LoadResourceFont and tried the following code:

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.

By the way: I know that I should have redistribution rights for the font if I need to embedded it into my EXE file.

But the problem is that if the font name ( I have used My Custom Font1, My Custom Font2) is not the actual name of the font, the font does not load properly and shows an unknown font character.

My question is that whether though I have used ResStream.Free in the founctions, yet I have to define again FormClose and FormDestroy event to protect Memory Leakage or not?

Community
  • 1
  • 1
HP Owner
  • 51
  • 4
  • 12
  • 'Label2.Font[2]' why should it compile? What do you want that statement to mean? – Sertac Akyuz Mar 25 '16 at 17:23
  • I need that Label1 Font should be loaded from RCDATA Type Resource and Label2 Font should be loaded from FONT Type Resource. – HP Owner Mar 25 '16 at 17:32
  • How about looking up the definitions of your functions? That will stop you assigning booleans to strings. It will also tell you what to with the return values of your functions. – Jan Doggen Mar 25 '16 at 17:41
  • Do you understand the concept of type mismatch? – David Heffernan Mar 25 '16 at 17:52
  • 1
    Anyway. You need to add the font and then check that succeeded. You don't do that. Then you refer to the font by name as with any other font. That's it. It pays to think about what code does rather than blindly copying it. Read it. Understand it. Think about what it does. Read documentation. Don't copy blindly and try stuff at random without any understanding. – David Heffernan Mar 25 '16 at 17:56
  • If anybody rectify my blindly copied code and make it compileable, it will be better to me to understand the wrong thing. – HP Owner Mar 25 '16 at 19:36
  • Possible duplicate of [Embedding a font in delphi](http://stackoverflow.com/questions/2984474/embedding-a-font-in-delphi) – Sir Rufo Mar 25 '16 at 19:52
  • Just realized that my dupe vote is already linked in the question - sorry – Sir Rufo Mar 25 '16 at 19:54
  • @HPO - You have what you need in David's comment. You also have it in your code: label1's font assignment works correctly. So why don't you try the same thing with label2? – Sertac Akyuz Mar 25 '16 at 20:28
  • Note that the [linked] code leaves the cleanup to the OS, it releases the resource when the application is closed. – Sertac Akyuz Mar 25 '16 at 20:31
  • @SertacAkyuz: *label1's font assignment works correctly*. No, it doesn't. The code assigns a boolean to `Label1.Font.Name`, which is the first compiler error at line 41. The first line 42 error is the assignment to `Label2.Font[2]`, because TFont does not have a default property. – Ken White Mar 26 '16 at 02:28
  • 1
    @Ken, OK I see, thanks for correcting. – Sertac Akyuz Mar 26 '16 at 02:32

2 Answers2

7

Your code has several errors in it.

  1. LoadResourceFont() returns a Boolean. You are trying to assign that value to the TLabel.Font.Name property, which you cannot do since a Boolean is not a String. You are also trying to assign the Boolean to a TLabel.Font[2] property, which is not even a valid identifier to assign a value to.

  2. Your first call to LoadResourceFont() is specifying the wrong resource name.

  3. The first parameter of LoadResourceFont() is a String, but your second call to LoadResourceFont() is trying to pass the global Hinstance variable (an THandle) where a String is expected.

  4. You are trying to load the second font as an RCDATA resource when it is actually a FONT resource instead.

To do what you are attempting, you need to call LoadResourceFont() first to load the font(s) into the font table, and then you can set the TLabel.Font.Name to the typeface name of the desired font (the name defined inside the TTF file, not the filename or resource name), eg:

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;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I suspect this won't work as AddFontMemResourceEx looks like it is retrieving a pseudo handle. Think about when font count is greater than 1, which font's handle will be returned. Also RemoveFontMemResourceEx calls the handle " a handle to a font-resource", which is more accurate I believe. – Sertac Akyuz Mar 25 '16 at 23:56
  • @SertacAkyuz: thanks, I updated my answer. – Remy Lebeau Mar 26 '16 at 00:10
  • @Sertac Akyuz: You are absolutely right. First chance exception at $75965B68. Exception class EResNotFound with message 'Resource 2 not found'. Process Project1.exe (19900) and the Label2 Font is also not loaded. – HP Owner Mar 26 '16 at 17:13
  • @HPOwner That would make sense if your second resource is getting compiled into the executable using a string name of `'2'` instead of a numeric ID of `2`. Check your executable with a resource viewer. Try `LoadResourceFontByName('2')` – Remy Lebeau Mar 26 '16 at 18:34
  • 1
    @HPO - That's a different error in which you are either not compiling the font resource into the executable, or not identifying it correctly. According to the picture in your question, you may have to change RT_RCDATA to RT_FONT in Remy's code. Also check the executable with an external resource editor to verify the font resource's existence and its identifier. – Sertac Akyuz Mar 26 '16 at 21:16
  • ... you have to begin trying to understand the code you use. – Sertac Akyuz Mar 26 '16 at 21:18
  • @SertacAkyuz good point about `RT_FONT`, I missed that in the screenshot. I updated my answer. – Remy Lebeau Mar 26 '16 at 21:54
  • @Remy Lebeau: Code is compiling, exe is running without any error, but UNKNOWN FONT is loaded not from RESOURCE. I have banned for questioning, so I am unable to ask this error again. Kindly unbar me. – HP Owner Apr 01 '16 at 18:39
  • @HPOwner: you are not banned, you can still [edit your question](http://stackoverflow.com/posts/36224624/edit) to make it better, then it may be reopened for answering. – Remy Lebeau Apr 01 '16 at 18:44
0

Label.Font doesn't have subscripts, so Label2.Font[2] is invalid.

Also, assigning the boolean result of your LoadFontResource function to a Label.Font of any kind will clearly not work, as that boolean result will never be a font.

I'd suggest you learn the basics of programming using Delphi and also study the VCL/FMX documentation for TFont before worrying about loading custom fonts from memory.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • 2
    I'm not sure this really answers the question. – Rob Kennedy Mar 25 '16 at 19:05
  • Really this is not solved my problem. I need to compile and work correctly my code. – HP Owner Mar 25 '16 at 19:31
  • 4
    @Rob: The question says *I'm not able to compile*. I explained why it won't compile - it's invalid code for the reasons I described. There is no other question asked or problem described (the title does neither). – Ken White Mar 25 '16 at 20:10